vue jsx 封装Table 表格+Tree 树形控件

背景介绍

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

图片预览

vue jsx 封装Table 表格+Tree 树形控件_第1张图片

需求分析

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

树形结构设置层级

层级部分数据如下图所示

vue jsx 封装Table 表格+Tree 树形控件_第2张图片

设置第一层

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)}})
} 

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)}})
} 

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);}})

} 

将归属于第一层的数据以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)}})
} 

将归属于其他层的数据以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);}}
} 

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;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);}})
} 

扁平化结构转换树形结构

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);}})
} 

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

从选中方法开始

//选中勾选框
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);}})//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);}})}
} 

更多源码请查看:

gitee地址

github地址

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

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

最后

整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。

有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享

部分文档展示:



文章篇幅有限,后面的内容就不一一展示了

有需要的小伙伴,可以点下方卡片免费领取

你可能感兴趣的:(vue.js,前端,javascript)