基于Vue的动态通用table表格及dialog对话框处理技巧总结

前言:采用vue并结合element-ui制作网页端管理系统中的表格是不难的,对应的form,table,dialog基本都有现成的样例,再结合vue基于数据的方式,很轻松就可以实现一个表格展示并进行动态添加,那么问题来了,如果一个管理系统中有很多表格,难道我们要一个一个去制作?就没有一个一劳永逸的解决办法么?只要制作一个table模板,给我要展示的数据,告诉要展示那些列,就能自动生成表格?答案是有的,下面我就如何用vue处理这种情况的方式技巧进行说明。源代码已经上传到gitee中,连接地址在文末给出。


1.效果图展示(都是动态生成的):

2.项目目录说明

由于本案例仅仅是一个demo,所以组件很少,其中components中common.js主要是对数据进行clone操作(因为js数据都是引用类型,不clone会一处动处处动),models中的数据主要负责table中展示那些列,和dialog中展示那些数据。models中数据原来也在APP根组件中,后来整合到models中。table组件就是展示表格的组件,myDialog组件就是展示对话框的组件。filter文件就是过滤器,负责对时间戳和男女性别等数据进行转换使用。下面进入正文。

3.针对table表格

其实动态表格的核心就是展示数据的传输控制列的展示,先看一下不是动态的情况下表格代码是什么样子的。

普通情况:

<el-table  stripe :data="mydata" 
                @select-all="selection=$event"
                @select='selection=$event'>
                    <el-table-column label='编号' type='selection' align='center' width='50'></el-table-column>
                     <el-table-column label='姓名' prop='name' align='center' width='120'></el-table-column>
                    <el-table-column label='年龄' prop='age' align='center'></el-table-column>
                    <el-table-column label='日期' align='center'>
                        <template slot-scope="scope">
                            <slot name="myDate" :myDateData="scope.row"></slot>
                        </template>
                    </el-table-column>
                    <el-table-column label='随便' align='center'>
                        <template slot-scope="scope">
                            {
   
   {scope.row.name}}+{
   
   {scope.row.age}}
                        </template>
                    </el-table-column>
 <el-table-column label='操作' align='center'>
                        <template slot-scope="scope">
                            <el-button-group>
                                <el-button type="primary" size="mini" @click="$emit('myEmit',scope.row)">编辑</el-button>
                                <el-button type="danger" size="mini" @click="$emit('myDelete',[scope.row])">删除</el-button>
                            </el-button-group> 
                        </template>
                    </el-table-column>
                </el-table>

调整为动态后:

 <el-table  stripe :data="mydata" 
                @select-all="selection=$event"
                @select='selection=$event'>
                    <el-table-column label='编号' type='selection' align='center' width='50'></el-table-column>
                    
                    <template v-for="item,index in myColsShow">
                        <!-- 非自定义内容且不是下拉框 -->
                        <el-table-column v-if="item.prop && item.type!=='select'" :label='item.label' :prop='item.prop' :align='item.align' :width='item.width'></el-table-column>
                        <!-- 非自定义内容但是是下拉框 -->
                        <el-table-column v-else-if="item.prop && item.type=='select'" :label='item.label' :prop='item.prop' :align='item.align' :width='item.width'>
                            <template slot-scope="scope">
                                <!-- 将性别男女进行转换 -->
                                {
   
   {scope.row.sex|transformSex}}
                            </template>
                        </el-table-column>
                        <!-- 自定义内容 -->
                        <el-table-column v-else :label='item.label'  :align='item.align' :width='item.width'>
                            <template slot-scope="scope">
                                <slot :name="item.slot" :myDateData="scope.row"></slot>
                            </template>
                        </el-table-column>
                    </template>
 <el-table-column label='操作' align='center'>
                        <template slot-scope="scope">
                            <el-button-group>
                                <el-button type="primary" size="mini" @click="$emit('myEmit',scope.row)">编辑</el-button>
                                <el-button type="danger" size="mini" @click="$emit('myDelete',[scope.row])">删除</el-button>
                            </el-button-group> 
                        </template>
                    </el-table-column>
                </el-table>

对应的列数据和表格内容数据:

//记录存放的元数据,即要展示的列,和对话框要展示的内容
let allDate=[
    {label:'姓名',prop:'name',align:'center',width:'120',type:'text',rule:[
        { required: true, message: '请输入姓名', trigger: 'blur'},
        { min: 2, max: 5, message: '名字长度在 2 到 5 个字符', trigger: 'blur',}
    ]},
    {label:'性别',prop:'sex',align:'center',type:'select'},
    {label:'密码',prop:'password',align:'center',type:'password',IsShow:false},
    {label:'文件',prop:'file',type:'file',IsShow:false},
    {label:'日期',slot:'myDate',align:'center',type:'text'},
]

export default allDate;

调整为动态代码中:data="mydata"是从父组件APP中传递进来的展示数据,myColsShow是对models中列数据(如上)是否展示进行的一个过滤(models中增加了IsShow属性)。代码如下

 //对数据展示的列进行一个过滤,有些敏感列不展示
      myColsShow(){
          //只展示isshow为true的,必须用强等于。因为没写这个isshow的属性的算是true,
          return this.myCols.filter(item=>item.IsShow!==false)
      }

在el-table中必须要给定data数据,同时在el-table-column中用prop属性绑定数据key值,就可以展示表格了。如果要自定义表格,就不用prop属性,通过prop是否存在判断是否为自定义列。然而在标签内设置插槽slot,其中是为了获取当前行的全部数据通过插槽作用域传递给父级,才是真正的插槽预留位,通过插槽作用域将数据传递到父级template中便于对日期等数据进行处理,最后再通过插槽将数据拿回来展示(具体的看源码)

核心思想通过v-for对要展示的列进行循环,通过v-if、v-else-if进行判断展示的是那种情况列(后期还可以动态补充)

插槽作用域看这篇文章:

https://www.jianshu.com/p/0c9516a3be80

4.针对dialog对话框

dialog对话框的情况也是类似于table表格,先绑定数据(和表格公用数据),之后通过循环确定要展示的列,根据v-if进行判断列的类型进行展示。代码如下:

<el-dialog width='30%' title="提示" :visible.sync="dialogVisible" 
        :before-close="handleClose" :destroy-on-close='true'>      
            <el-form ref="myForm" :model="myForm" label-width="60px">
                <!-- 动态组织表单内容 -->
                <el-form-item v-for="item,index in dialogItem" 
                :key='index' :label="item.label" :prop="item.prop" 
                :rules="item.rule">
                    <!-- 【1】如果是普通文本 -->
                    <el-input v-if="item.type=='text'" type='text' 
                    v-model="myForm[item.prop]"></el-input>
                    <!-- 【2】如果是密码 -->
                    <el-input v-else-if="item.type=='password'" type='password' 
                    v-model="myForm[item.prop]"></el-input>
                    <!-- 【3】如果是数字 -->
                    <el-input v-else-if="item.type=='number'" type='number' 
                    v-model="myForm[item.prop]"></el-input>
                    <!-- 【4】如果是上传文件 -->
                    <el-upload v-else-if="item.type=='file'" 
                     action="https://jsonplaceholder.typicode.com/posts/">
                        <el-button size="small" type="primary">点击上传</el-button>
                    </el-upload>   
                    <!-- 【5】如果是下拉框-->
                    <el-select v-else-if="item.type=='select'" v-model="myForm[item.prop]" placeholder="请选择">
                        <el-option  label="男" value='male'></el-option>
                        <el-option  label="女" value='female'></el-option>
                    </el-select>
                </el-form-item>
            </el-form>

            <template slot="footer" >
                <el-button @click="closeDialog()">取 消</el-button>
                <el-button type="primary" @click="myDate">确 定</el-button>
            </template>
        </el-dialog>

这里我只列举了五种情况,后续若有新的数据形式仍然可以动态添加。

效果如下:

5.动态页码

这里面在动态页码处理的时候出现了子组件更改父组件的情况,我用到了.sync的用法,代码如下:

<!-- 页码 -->
       <el-row type="flex" justify="space-between" :gutter="20">
           <el-col :span='6'></el-col>
           <el-col :span='12'>
               <!-- 显示页码条数 -->
               {
   
   {page}}
               <el-pagination :current-page.sync='curPage' :total='total' 
               :size='size'>
               </el-pagination>
           </el-col>
           <el-col :span='6'></el-col>
       </el-row>

针对.sync具体用法看如下连接:

官网:https://cn.vuejs.org/v2/guide/components-custom-events.html#sync-%E4%BF%AE%E9%A5%B0%E7%AC%A6

其他:https://www.jianshu.com/p/6b062af8cf01

6.总结:

本文对动态表格和对话框的思路进行简单说明,核心就是写了个框架,其他地方只要给数据,要展示的列就可生成对应表格,并且可以和对话框关联。因为这里面涉及较多的组件间通信,所以通过叙述很难描述的清楚。

为此我把全部项目demo放到了gitee中,想要研究的同学可以自行下载。

gitee连接:

https://gitee.com/fan-shuchang/The-dynamic-form

猜你喜欢

转载自blog.csdn.net/qq_42539194/article/details/111414042