• vue jsx 封装Table 表格+Tree 树形控件 jsx自定义el-table-column


    背景介绍

    通过表格展示树的层级,可通过对树的勾选对每一个界面的dom元素进行控制,控制程度可精确到组件/标签

    图片预览

    效果预览

    需求分析

    1. 根据树形结构获取层级(列数)
    2. 根据数据动态控制表格列数
    3. 格式化表格内容
    4. 将单元格内容(扁平化)转为结构化数据
    5. 勾选/取消勾选时关联相关层级

    树形结构设置层级

    层级部分数据如下图所示

    层级部分数据

    设置第一层

    data(){
        return {
            index: '', //自定义列内容出现index未定义报错,需加上index参数
            numberList:[],
            num:0
        }
    }
    
    deepTableDataFirstLevel(data){ //setting first level 第一层
        var that = this;
        that.num ++;
        if(that.numberList.indexOf(that.num) == -1){
            that.numberList.push(that.num);
        }
        data.filter(v=>{
            that.$set(v,'level',that.num);
            that.$set(v,'parentId',0);
            if(v.children && v.children.length > 0){
                that.deepTableDataOrderLevel(v.children,(that.num+1),v.id)
            }
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    num为层级

    第一层默认parentId为0

    numberList存储层级(储存标识防止重复层级)

    设置其他层

    deepTableDataOrderLevel(data,num,id){ //setting order level 其他层级
        var that = this;
        if(that.numberList.indexOf(num) == -1){
            that.numberList.push(num);
        }
        data.filter(v=>{
            that.$set(v,'level',num);
            that.$set(v,'parentId',id);
            if(v.children && v.children.length > 0){
                that.deepTableDataOrderLevel(v.children,(num+1),v.id)
            }
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    data为父级列表

    父级列表遍历设置相同层级

    每到下一层层级+1

    deepTableDataOrderLevel方法每执行一次就把当前对象(存在children情况下)递归该对象chilren参数列表并给其对象设置层级

    将相同层级数据转换为table列表数据

    转换第一层

    data(){
        return {
            num:0,
            index: '', //自定义列内容出现index未定义报错,需加上index参数
            columnData:[],
            levelObj:{}
        }
    }
    
    handleTable(data){ //setting first level 第一层
        var that = this;
        that.columnData = [];
        that.levelObj = {};
    
        data.filter((v,index)=>{
            that.$set(that.columnData,index,{label:v.label,value:v.id,id:v.id,parentId:v.parentId})
            if(v.children && v.children.length > 0){
                that.numberList.filter(n=>{
                    that.levelObj[('level'+n)] = [];
                })
                that.$set(that.columnData[index],'level1',[{label:v.label,value:v.id,id:v.id,parentId:v.parentId,checked:false}]);
                that.deepTableList(v.children,index);
            }
        })
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    将归属于第一层的数据以level+层级以数组形式添加到columnData并设置默认为取消的勾选参数

    转换其他层

    deepTableList(data,num){ //setting order level 其他层级
        var that = this;
        data.filter(v=>{
            if(that.numberList.indexOf(v.level) > -1){
                that.levelObj['level'+v.level].push({label:v.label,value:v.id,id:v.id,parentId:v.parentId,checked:false});
                that.$set(that.columnData[num],'level'+v.level,that.levelObj['level'+v.level]);
            }
            if(v.children && v.children.length > 0){
                that.deepTableList(v.children,num)
            }
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    将归属于其他层的数据以level+层级以数组形式添加到columnData并设置默认为取消的勾选参数

    动态控制表格列数并格式化内容

    这里使用渲染函数jsx进行处理

    
    components:{
        TableColumn:{
            props:{
                node:{
                    default(){
                        return {}
                    }
                },
                num:{
                    default(){
                        return []
                    }
                },
            },
            render(h){
                const superParams = this.$parent.superParams;
                const parent = this.$parent;
                const node = this.node;
                const num = this.num;
                let tableRowList = []; //防止重复数据
                let rowIdList = [];
                const renderContent = (row, column, cellValue, index) => { //格式化内容
                    //()=>parent.checkMenu(row) 防止立刻触发
                    cellValue && cellValue.filter(v=>{
                        if(rowIdList.indexOf(v.id) == -1){
                            rowIdList.push(v.id);
                            tableRowList.push(v);
                        }
                    })
                    return cellValue && cellValue.map((item,index) => superParams.checkMenu(item,tableRowList)} v-model={item.checked}>{item.label})
                }
                const templateNode =  
                 
                    {
                        num.map((v,index)=>  2 ? 350 : 180} prop={'level'+v} label={'level'+v} key={index} formatter={renderContent} />)
                    }
                
    
                return (templateNode);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    superParams为最高层组件参数通过(inject: [‘superParams’])引入

    parent为父级参数

    num为数据的层级

    通过num实现对el-table-column列数的展示

    formatter格式化内容

    cellValue为单元格内容,这里将单元格内容设置为Checkbox 多选框

    checkMenu为最高级组件方法并携带当前行参数(row),所有row参数(tableRowList)(扁平化结构)

    由于cellValue单元格内容为单独的对象形式的数据,需要对其转换为结构化,并保证该checked为响应式

    将单元格内容(扁平化)转为结构化数据

    勾选后对数据进行处理

    data(){
        return {
            editForm: {
                menuIds:[]
            },
            deepPermTreeData:[],
            rowTree:[],
            levelParentIdList:[]
        }
    }
    checkMenu(row,tableRowList){ //id必须唯一(否则会出现无法关联的问题)
        this.editForm.menuIds = [];
        this.tableRowTree(tableRowList);
        this.deepPermTreeData = tableRowList;
        his.$set(row,'firstSelect',row.id);
        this.searchParent(row);
        tableRowList = this.rowTree;
        //对已有的数据进行回显
        this.deepPermTreeData.filter(v=>{
            if(v.checked){
                this.editForm.menuIds.push(v.id);
            }
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    扁平化结构转换树形结构

    import _ from 'lodash' //需引入
    //初始化树形结构
    tableRowTree(list){
        var that = this;
        that.rowTree = [];
        list.filter(v=>{
            if(v.parentId == 0){
                that.rowTree.push(v);
            }
        })
        that.tableRowChildrenTree(that.rowTree,list);
        list = that.rowTree;
    },
    //扁平化结构转为树形结构
    tableRowChildrenTree(data,list){ 
        var that = this;
        data.filter(v=>{
            if(_.filter(list,['parentId',v.id]).length > 0){
                that.$set(v,'children',_.filter(list,['parentId',v.id]));
            }
            if(v.children){
                that.tableRowChildrenTree(v.children,list);
            }
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    勾选/取消勾选时关联相关层级

    从选中方法开始

    //选中勾选框
    checkMenu(row,tableRowList){ //id必须唯一(否则会出现无法关联的问题)
        this.editForm.menuIds = [];
        this.tableRowTree(tableRowList);
        this.deepPermTreeData = tableRowList;
        this.$set(row,'firstSelect',row.id);
        this.searchParent(row);
        tableRowList = this.rowTree;
        //对已有的数据进行回显
        this.deepPermTreeData.filter(v=>{
            if(v.checked){
                this.editForm.menuIds.push(v.id);
            }
        })
        //console.log(this.editForm.menuIds);
    },
    
    //查找父级id
    searchParent(row){
        this.deepPermTreeData.filter(v=>{
                if(row.parentId == 0){ //当前级别为最高级别
                    if(row.id == v.parentId){ //当前最高级别的子级
                        if(row.checked){ //当前元素为勾选状态
                            this.$set(v,'checked',true); //对当前元素的子级进行勾选
                            this.checkList = [];
                            this.deepCheckedChildList(row.children);
                            this.checkedRoleList(this.checkList);
                        }else { //当前元素为取消勾选状态
                            this.$set(v,'checked',false); //对当前元素的子级取消勾选
                            this.checkList = [];
                            this.deepCheckedChildList(row.children);
                            this.unCheckedRoleList(this.checkList);
                        }
                    }
                }else {
                    if(v.id == row.parentId){ //当前级别不是最高级别/当前元素父级
                        if(row.checked){ //当前元素已勾选
                            this.$set(v,'checked',true); //勾选父级
                            this.levelParentIdList = [];
                            this.searchLevelParent(this.deepPermTreeData,v.parentId);
                            this.checkedRoleList(this.levelParentIdList);
                            this.checkList = [];
                            this.deepCheckedChildList(row.children);
                            this.checkedRoleList(this.checkList);
                        }else{ //当前元素取消勾选
                            this.deepunCheckedRoleList(v,row.id);
                            this.checkList = [];
                            this.deepCheckedChildList(row.children);
                            this.unCheckedRoleList(this.checkList);
                        }
                    }
    
                }
        })
    },
    //逆向查找各层父节点
    searchLevelParent(data,parentId){
         var that = this;
         data.filter(v=>{
             if(v.id == parentId){
                 that.levelParentIdList.push(v.id);
                 that.searchLevelParent(data,v.parentId); //存在上一层则继续查找父级
             }else if(v.children && v.children.length > 0){
                 that.searchLevelParent(v.children,parentId);
             }
         })
     },
    //勾选对应的权限
    checkedRoleList(idList){
        this.deepPermTreeData.filter(v=>{
            if(idList.indexOf(v.id) > -1){
                this.$set(v,'checked',true); 
            }
        })
    },
    //取消勾选对应的权限
    unCheckedRoleList(idList){
        this.deepPermTreeData.filter(v=>{
            if(idList.indexOf(v.id) > -1){
            	this.$set(v,'firstSelect','');
                this.$set(v,'checked',false); 
            }
        })
    },
    //递归遍历
    deepunCheckedRoleList(list,id){
        var isChecked = [];
        var unChecked = [];
        isChecked = _.filter(list.children,['checked',false]); //同级节点未勾选列表
        unChecked = _.filter(list.children,['checked',true]); //同级已勾选的节点
        if(isChecked.length == list.children.length){ //同级元素都取消勾选
            var listId = [];
            listId.push(list.id);
            this.unCheckedRoleList(listId); //取消勾选父级
            if(list.parentId != 0){
                var parentObj = this.searchRoleList(list.parentId); //找出父级的同级
                this.deepunCheckedRoleList(parentObj,parentObj.id);
            }
        }else {
            var list = [];
            list.push(id);
            //this.unCheckedRoleList(list);
        }
    },
    //找到对应父节点列表
    searchRoleList(id){
        var list = {};
        this.deepPermTreeData.filter(v=>{
            if(id == v.id){
                list = v;
            }
        })
        return list;
    },
    //勾选子列表
    deepCheckedChildList(row){
        if(row && row.length > 0){
            row.filter(v=>{
                this.checkList.push(v.id);
                if(v.children){
                    this.deepCheckedChildList(v.children);
                }
            })
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125

    更多源码请查看:

    gitee地址

    github地址

    父组件目录:vue-element-data\src\views\roleManage\addRole

    子组件目录:vue-element-data\src\components\Page\elTableTree

  • 相关阅读:
    tensorflow2.0 mnist手写数字识别 并验证几张图片以查看效果
    手机注册.
    C#源码 LIS实验室(检验科)信息系统源码 SaaS模式的Client/Server架构
    LeetCode(Python)—— 多数元素(简单)
    Python超入门(4)__迅速上手操作掌握Python
    Ribbon的轮询策略实现方法
    【Raspberry Pi】搭建NAS流媒体播放器 + ARIA2 + YAAW + 迅雷下载系统
    Spring 框架下如何调用kafka
    计算机网络——b站王道考研笔记
    Ubuntu: 系统使用, 系统源更新, Vi基本操作, 磁盘拓展
  • 原文地址:https://blog.csdn.net/mrliucx/article/details/126039859