美文网首页基础前端
json-server 和 mockjs 配合 iview 制作

json-server 和 mockjs 配合 iview 制作

作者: CondorHero | 来源:发表于2019-09-25 18:53 被阅读0次

    前言:使用到的技术

    • josn-server 创建数据库的富查询
    • mockjs 生成数据
    • iview 框架,涉及到两个重要的 API 是PageTablehttps://www.iviewui.com/components/table
    • vuex 作为统一状态管理容器
    • vue 技术

    项目本来是很简单的,结果业务越加越多就积重难返了,就不那么容易懂了,刚开始写的代码最能体现出思路,但是不好看,后来进行代码优化合并,就造成理解困难。所以除了注释还把所有的源码放上去以帮助自己和有兴趣的人理解。

    一开始我们首先的通过:json-server --watch db.json 命令打开我们生成的假数据,并通过http://localhost:3000/students能看到如下数据:

    数据接口情况

    假数据的制作请参考上篇文章。

    最后的实现效果大约是这样的:


    学生管理列表

    上面的那个效果,完全是修改好的版本。还好我在写的时候把前期的代码留下来了,当做个思路入门,现讲这个简易版的。

    一、入口文件配置

    main.js 作为入口文件在这里配置 iview 和 vuex。

    import Vue from "vue";
    import App from "./App.vue";
    import Vuex from "vuex";
    import iview from 'iview';
    import store from "./store/index";
    // Vuex作为插件使用
    Vue.use(Vuex);
    // iview作为插件使用
    // 子组件可直接使用iview里面的组件
    Vue.use(iview);
    
    new Vue({
        el:"#app",
        render(h){
            return h(App);
        },
        store:new Vuex.Store(store)
    });
    

    相应的 index.html 就是这样:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Vue 学习</title>
    <link rel="stylesheet" href="./styles/iview.css">
    </head>
    <body>
        <div id="app"></div>
        <script src = "./virtual/bundle.js"></script>
    </body>
    </html>
    
    二、页面框架搭建

    App.vue 搭建页面和事件处理

    <template>
        <div>
            <div class="box">
                <h1>学生表格</h1>
                <!-- 表格 stripe隔行变色 border单个单元格有边框-->
                <!-- draggable开启拖拽 并使用拖拽的配套事件@on-drag-drop="drag"-->
                <!--  :columns定义表头 :data表格数据-->
                <Table stripe border draggable @on-drag-drop="drag" :columns="columns" :data="data"></Table>
                <!-- 分页 :total总页数current当前页面,更改页面的点击事件@on-change-->
                <Page :total="total" :current="page" @on-change="changePage"/>
            </div>
        </div>
    </template>
    
    <script>
        export default {
            // 组件创建前进行数据初始化,发送Ajax
            beforeCreate(){
                this.$store.dispatch("stu/loadData",{page:1});
            },
            methods:{
                // 更改page触发事件
                changePage(page){
                    this.$store.dispatch("stu/loadData",{page});
                },
                // 拖拽事件
                drag(index1, index2){
                    this.$store.commit("stu/drag",{index1,index2});
                }
            },
            computed:{
                columns(){
                   return this.$store.state.stu.arr;
                },
                data(){
                    return this.$store.state.stu.data;
                },
                total(){
                    return this.$store.state.stu.total;
                },
                page(){
                    return this.$store.state.stu.page;
                }
            }
        }
    </script>
    
    <style scoped>
    .box{
        width: 1000px;
        margin:50px auto;
        text-align:center;
    }
    </style>
    
    三、vuex处理数据

    stu.js 标准的 vuex 数据结构。

    // 引入axios用来发送Ajax
    import axios from "axios";
    // 以下标准的Vuex
    export default {
        // 命名空间
        namespaced :true,
        // 统一的状态容器
        state :{
            // 表格的表头
            arr : [
                {title:"id",key:"id",render: (h, params) => {
                    // 附赠的render可以替换前面的内容
                    // 列内容全部在params的row里面
                    return h('div', [
                        h('i', params.row.id)
                    ]);
                }},
                {title:"name",key:"name",align:"center"},
                // sortable: true开启字段排序
                {title:"age",key:"age",sortable: true},
                {title:"province",key:"province"},
                {title:"sex",key:"sex"},
                {title:"education",key:"education"}
            ],
            // 表格的数据
            data  : [],
            // 表格的总页数
            total : 0,
            // 表格的当前页面
            page  : 1
        },
        // 同步请求commit
        mutations:{
            // 数据的初始化
            initdata(state,{data,total,page}){
                state.data = data;
                state.total = Number(total);
                state.page = page;
            },
            // 拖拽排序
            drag(state,{index1,index2}){
                console.log(typeof index1,typeof index2);
                state.data = state.data.map((item,index)=>{
                    if(index == index1){
                        return state.data[index2]
                    }else if(index == index2){
                        return state.data[index1]
                    }
                    return item;
                });
            }
        },
        // 异步请求dispatch
        actions:{
            // 初始化发送Ajax请求数据
            loadData({commit},{page}){
                axios.get(`http://localhost:3000/students?_page=${page}&_limit=10`).then(data=>{
                    commit("initdata",{data:data.data,total:data.headers["x-total-count"],page});
                    console.log(data.headers["x-total-count"]);
                })
            }
        }
    }
    

    把 stu.js 进行暴露到全局,以和 App.vue 进行通信:

    import stu from "./stu.js";
    export default {
        modules:{
            stu
        }
    }
    
    四、改进版

    上面的代码,明显功能还不够完善,基本没啥技术活。下面进行改进。
    stu.js 是改进最多了,改动痕迹可以和上面的初始版本对比,初始版本里面没有的,我也在新版本对改进的地方进行了注释,并没有完全擦除掉改动痕迹。

    // 引入axios用来发送Ajax
    import axios from "axios";
    // 以下标准的Vuex
    export default {
        // 命名空间
        namespaced :true,
        // 统一的状态容器
        state :{
            // 表格的表头
            arr : [
                {title:"序号",key:"id",render: (h, params) => {
                    // 附赠的render可以替换前面的内容
                    // 列内容全部在params的row里面
                    return h('div', [
                        h('i', params.row.id)
                    ]);
                },align:"center"},
                {title:"头像",key:"avatar",align:"center",render(h,params){
                    return h('div', {style:{width:'50px',height:'50px',backgroundSize:"contain",backgroundImage:`url(${params.row.avatar})`,margin:"5px auto"}},"")
                }},
                // 表格内容默认左对齐,align:"center"居中
                {title:"姓名",key:"name",align:"center"},
                // sortable: true开启字段排序
                {title:"年龄",key:"age",sortable: true,align:"center"},
                // 表格筛选是否是共青团员
                {
                    title:"共青团员",
                    key:"member",
                    align:"center",
                    // 筛选共青团
                    filters: [
                                {
                                    // label显示筛选条件
                                    // value是其对应的值,不一定是Boolean值
                                    label: "是共青团员",
                                    value: true
                                },
                                {
                                    label: "不是共青团员",
                                    value: false
                                }
                            ],
                    // 是否开启多条件筛选默认打开
                    filterMultiple: false,
                    // 筛选函数必须
                    filterMethod (value, row) {
                        if (value) {
                            return row.member === "是";
                        } else{
                            return row.member === "否";
                        }
                    }
                },
                {title:"省份",key:"province",align:"center"},
                {title:"性别",key:"sex",align:"center"},
                {title:"教育情况",key:"education",align:"center"},
                {title:"民族",key:"national",align:"center"},
            ],
            // 表格的数据
            data  : [],
            // 表格的总页数
            total : 0,
            // 表格的当前页面
            page  : 1,
            // 每页显示条数
            pagesize : 5,
            // Ajax发送的民族查询接口
            national : "",
            // 模糊查询的输入值
            inputValue :""
        },
        // 同步请求commit
        mutations:{
            // 数据的初始化
            initdata(state,{data,total,page}){
                state.data = data;
                state.total = Number(total);
                state.page = page;
            },
            // 拖拽排序
            drag(state,{index1,index2}){
                console.log(typeof index1,typeof index2);
                state.data = state.data.map((item,index)=>{
                    if(index == index1){
                        return state.data[index2]
                    }else if(index == index2){
                        return state.data[index1]
                    }
                    return item;
                });
            }
        },
        // 异步请求dispatch
        actions:{
            // 初始化发送Ajax请求数据
            loadData({commit,dispatch,state},{page,pagesize}){
                state.page = page;
                // 因为loadData检测两个事件,所以防止 pagesize 不存在
                pagesize ? state.pagesize = pagesize : 5;
                dispatch("dispatchAjax");
                // let national = state.national ? "&"+state.national : "";
                // console.log(national)
                // axios.get(`http://localhost:3000/students?_page=${page}&_limit=${state.pagesize}${national}`).then(data=>{
                //  commit("initdata",{data:data.data,total:data.headers["x-total-count"],page});
                //  console.log(data.headers["x-total-count"]);
                // });
            },
            checkedArr({commit,dispatch,state},{checkedArr}){
                // 筛选民族的时候把数组给转化成URL
                state.national = checkedArr.length ? "&"+checkedArr.map(item=>`national=${item}`).join("&") : "";
                state.page = 1;
                dispatch("dispatchAjax");
                // axios.get(`http://localhost:3000/students?_page=${state.page}&_limit=${state.pagesize}${state.national}`).then(data=>{
                //  commit("initdata",{data:data.data,total:data.headers["x-total-count"],page:state.page});
                // });
            },
            // 模糊查询的接口
            inputChange({commit,dispatch,state},{inputValue}){
                state.page = 1;
                state.inputValue = inputValue ? `&q=${inputValue}` : "";
                dispatch("dispatchAjax");
                // axios.get(`http://localhost:3000/students?_page=_page=${state.page}&_limit=${state.pagesize}&q=${state.inputValue}`).then(data=>{
                //  commit("initdata",{data:data.data,total:data.headers["x-total-count"],page:state.page});
                // });
            },
            // 把全部的Ajax请求提取出来
            dispatchAjax({commit,state}){
                axios.get(`http://localhost:3000/students?_page=${state.page}&_limit=${state.pagesize}${state.national}${state.inputValue}`).then(data=>{
                    commit("initdata",{data:data.data,total:data.headers["x-total-count"],page:state.page});
                })
            }
        }
    }
    

    主文件 App.vue 只是稍稍增加了一点功能:

    <template>
        <div>
            <div class="box">
                <div>
                    查询数组:{{checkGroup}}
                    <!-- 筛选 -->
                    <Row>
                        <Col :span="2">筛选民族:</Col>
                        <Col :span="22">
                            <CheckboxGroup
                            v-model="checkGroup"
                            @on-change="checkedgroup"> 
                                <Checkbox v-for="i in national" :key="i" :label="i"></Checkbox>
                            </CheckboxGroup>
                        </Col>
                    </Row>
                </div>
                <div>
                    <Row>
                        <Col span="4">
                            <Input placeholder="模糊查询" ref="inputTxt"/>
                        </Col>
                        <Col span="2">
                            <Button @click="inputChange">查询</Button>
                        </Col>
                        <Col span="2">
                            <Button @click="clear">清空</Button>
                        </Col>
                    </Row>
                </div>
                <h1>学生表格</h1>
                <!-- 表格 stripe隔行变色 border单个单元格有边框-->
                <!-- draggable开启拖拽 并使用拖拽的配套事件@on-drag-drop="drag"-->
                <!--  :columns定义表头 :data表格数据-->
                <Table
                stripe
                border
                draggable
                @on-drag-drop="drag"
                :columns="columns"
                :data="data"
                />
                <!-- 分页 :total总页数current当前页面,更改页面的点击事件@on-change-->
                <Page
                :total="total"
                :current="page"
                :page-size="pageCount"
                :page-size-opts="[3,5,8,10]"
                @on-change="changePage"
                @on-page-size-change="changeSize"
                show-total
                show-elevator
                show-sizer
                />
            </div>
        </div>
    </template>
    
    <script>
        import national from "./national.js";
        export default {
            data(){
                return {
                    national,
                    checkGroup:[]
                }
            },
            // 组件创建前进行数据初始化,发送Ajax
            beforeCreate(){
                this.$store.dispatch("stu/loadData",{page:1});
            },
            methods:{
                // 更改page触发事件
                changePage(page){
                    this.$store.dispatch("stu/loadData",{page});
                },
                // 拖拽事件
                drag(index1, index2){
                    this.$store.commit("stu/drag",{index1,index2});
                },
                // 每页显示条数
                changeSize(pagesize){
                    this.$store.dispatch("stu/loadData",{page:1,pagesize});
                },
                // 民族筛选时,选中的数据作为数据发送出去
                checkedgroup(checkedArr){
                    this.$store.dispatch("stu/checkedArr",{checkedArr});
                },
                // 根据输入框的内容发送Ajax进行查找
                inputChange(){
                    this.$store.dispatch("stu/inputChange",{inputValue:this.$refs.inputTxt.currentValue});
                },
                // 清除输入框的内容和重新发送Ajax请求
                clear(){
                    this.$refs.inputTxt.currentValue = "";
                    this.$store.dispatch("stu/inputChange",{inputValue:""});
                }
            },
            computed:{
                columns(){
                   return this.$store.state.stu.arr;
                },
                data(){
                    return this.$store.state.stu.data;
                },
                total(){
                    return this.$store.state.stu.total;
                },
                page(){
                    return this.$store.state.stu.page;
                },
                pageCount(pagesize){
                    return this.$store.state.stu.pagesize;
                }
            }
        }
    </script>
    
    <style scoped>
    .box{
        width: 1000px;
        margin:50px auto;
        text-align:center;
    }
    .ivu-page{
        margin-top:20px;
    }
    </style>
    

    补充一下上面iview 框架 Table 表格里面 render 的用法。render 是用来自定义渲染列,使用的是 Vue 的 Render 函数。会传入两个参数,第一个是 h,第二个为对象,包含 row、column 和 index,分别指当前行数据,当前列数据,当前行索引。

    现在介绍的是 h 函数有三个参数时候的使用方法,中间参数能配置的东西。

    h(
        'Button', 
        {
            //配置框架标签自带属性
            props: {
                type: "primary",
                size: "small"
            }
        },
        params.row
    );
    h(
        //添加标签
        'img', 
        {
            //w3c官方标签的属性类似src,herf,style,id,class等
            attrs: {
                style:"margin:'20px'";
            },
            //sytle标签可以单独写出来
            {
                width;"200px";
            },
            //添加事件
            on: {
                click: (e) => {
                    e.stopPropagation();
                }
            },
            'class': {
                'cur': params.row.id === 2
            },
            //domProps添加节点属性
            domProps: {
                innerHTML: '...'
            }
        },
        //写入标签的内容
        params.row.content
    );
    

    文章完成于:
    2019.09.04

    相关文章

      网友评论

        本文标题:json-server 和 mockjs 配合 iview 制作

        本文链接:https://www.haomeiwen.com/subject/xmycyctx.html