项目是用vue做的,引入jquery-ztree实现树形菜单展示,为了化出想要的动态渲染表格效果,所以需要处理数据。
思路:表格合并,还是使用原生的表格嵌套(表格中嵌套表格)。对后端返回的数据进行处理。
首先看效果图:
后台返回的数据:
为了实现想要的结果就得对后台的数据进行处理:
处理步骤:
1、ztree为级联选中状态,因为只有选择1/2/3级节点才会出现想要的效果。首先为ztree添加选中事件
callback: {
onCheck: this.zTreeOnCheck
}
2、如果不知道zTreeOnCheck事件的请查阅ztree文档:http://www.treejs.cn/v3/api.php,因为我们设置的是级联选中,所以选中一级节点的话会默认选中一级节点下边所有的节点。所以会同时触发选中事件。至于点击一级节点、二级节点、三级节点、zTreeOnCheck事件是怎么接受参数的,请自行测试。直接上代码:
zTreeOnCheck(event, treeId, treeNode) {
//定义选中事件传递的参数
let data = {
qualitativeRulesDesc: treeNode.qualitativeRulesDesc,
qualitativeRulesId: treeNode.qualitativeRulesId,//ztree需要的数据格式
qualitativeRulesName: treeNode.qualitativeRulesName,//ztree需要的数据格式
qualitativeRulesPid: treeNode.qualitativeRulesPid,//ztree需要的数据格式
qualitativeRulesScore: treeNode.qualitativeRulesScore,
qualitativeRulesStatus: treeNode.qualitativeRulesStatus,//节点的级别,项目中只有三级
qualitativeRulesUpdator: treeNode.qualitativeRulesUpdator
};
if (treeNode.checked) {
// 选中的时候,因为设置的是级联,所以点击节点的话,会传递所有的节点。
// 第一次点击一级节点,就会讲所有的节点传递过来,依次加到数组selectedData中去
// 第二次直接点击该一级节点下的二级节点,还会将一级节点传递过来,所以这里对数据进行第一次处理,保证selectedData数组中的元素为所有的选中的元素。 至于ztree如何返回的,可以自己测试下,设置级联之后,数据返回比较奇葩。
for (let i = 0; i < this.selectedData.length; i++) {
if (
this.selectedData[i].qualitativeRulesId === data.qualitativeRulesId
) {
this.selectedData.splice(i, 1);
}
}
this.selectedData.push(data);
} else {
for (let i = 0; i < this.selectedData.length; i++) {
if (
this.selectedData[i].qualitativeRulesId === data.qualitativeRulesId
) {
this.selectedData.splice(i, 1);
}
}
}
// 调用处理数据方法
this.preView();
3、对selectedData数组进行数据处理,因为后续还需要使用所以提出一个方法。
preView() {
// vue return 中定义过dealNodes数组,因为动态渲染,所以每一次方法都需要重新给数组装载数据
this.dealNodes = [];
if (this.selectedData.length === 0) {
return false;
}
// 放入所有的一级节点数据
let levelOne = [];
// 放入所有的二级节点数据
let levelTwo = [];
// 放入所有的三级节点数据
let levelThree = [];
for (let i = 0; i < this.selectedData.length; i++) {
if (this.selectedData[i].qualitativeRulesStatus === 1) {
levelOne.push({
qualitativeRulesId: this.selectedData[i].qualitativeRulesId,
qualitativeRulesName: this.selectedData[i].qualitativeRulesName,
qualitativeRulesPid: this.selectedData[i].qualitativeRulesPid
});
} else if (this.selectedData[i].qualitativeRulesStatus === 2) {
levelTwo.push({
qualitativeRulesId: this.selectedData[i].qualitativeRulesId,
qualitativeRulesName: this.selectedData[i].qualitativeRulesName,
qualitativeRulesPid: this.selectedData[i].qualitativeRulesPid
});
} else if (this.selectedData[i].qualitativeRulesStatus === 3) {
levelThree.push({
qualitativeRulesId: this.selectedData[i].qualitativeRulesId,
qualitativeRulesName: this.selectedData[i].qualitativeRulesName,
qualitativeRulesPid: this.selectedData[i].qualitativeRulesPid,
qualitativeRulesDesc: this.selectedData[i].qualitativeRulesDesc,
qualitativeRulesScore: this.selectedData[i].qualitativeRulesScore
});
}
}
// 给dealNodes数组中添加一级节点
for (let m = 0; m < levelOne.length; m++) {
// 首先 给数组中加入根节点
this.dealNodes.push({
id: levelOne[m].qualitativeRulesId,
pId: levelOne[m].qualitativeRulesPid,
name: levelOne[m].qualitativeRulesName,
weight:"", // 项目中用到的可以根据自己的项目定义参数
//定义孩子节点,将后续的二级节点封装到children中
children: []
});
}
// 循环一级节点添加二级子节点
for (let n = 0; n < this.dealNodes.length; n++) {
for (let j = 0; j < levelTwo.length; j++) {
// 如果说当前二级节点的父节点 == 一级节点的话 那么说明该节点属于一级节点的子节点
if (levelTwo[j].qualitativeRulesPid == this.dealNodes[n].id) {
this.dealNodes[n].children.push({
id: levelTwo[j].qualitativeRulesId,
pId: levelTwo[j].qualitativeRulesPid,
name: levelTwo[j].qualitativeRulesName,
children: []
});
}
}
}
// 循环dealNodes数组给二级节点添加三级节点
for (let n = 0; n < this.dealNodes.length; n++) {
// 一级节点下的二级节点
for (let i = 0; i < this.dealNodes[n].children.length; i++) {
for (let k = 0; k < levelThree.length; k++) {
if (levelThree[k].qualitativeRulesPid == this.dealNodes[n].children[i].id) {
this.dealNodes[n].children[i].children.push({
id: levelThree[k].qualitativeRulesId,
pId: levelThree[k].qualitativeRulesPid,
name: levelThree[k].qualitativeRulesName,
desc: levelThree[k].qualitativeRulesDesc,
score: levelThree[k].qualitativeRulesScore
});
}
}
}
}
// 清空临时定义的一级节点数组
levelOne = [];
// 清空临时定义的二级节点数组
levelTwo = [];
// 清空临时定义的三级节点数组
levelThree = [];
}
4、数据已经处理好 接下来就要去渲染页面
<table class="treeTable" style="width: 90%;border-collapse: collapse;" border="1" cellpadding="0" cellspacing="0" >
<tr style="height: 20px;background-color:ghostwhite;">
<td class="th" style="text-align: center;width: 15%;">一级指标</td>
<td>
<table style="width: 100%;height: 40px;border-collapse: collapse;" cellpadding="0" cellspacing="0">
<tr>
<td style="width: 30%;text-align: center;border-right: 1px solid #000">二级指标</td>
<td style="width: 60%;text-align: center;border-right: 1px solid #000">三级指标</td>
<td style="width: 10%;text-align: center;">分数</td>
</tr>
</table>
</td>
</tr>
<tr v-for="(item,index) in dealNodes" :key="index">
<td style="text-align: center;width: 15%">{{item.name}}</td>
<td>
<table style="width: 100%;height: 100%;border-collapse: collapse;" cellpadding="0" cellspacing="0" >
<tr v-for="(firstItem,index) in item.children" :key="index">
<td style="width: 30%;text-align: center;border-right: 1px solid #000" v-if="item.children.length-1===index">
{{firstItem.name}}</td>
<td style="width: 30%;text-align: center;border-bottom: 1px solid #000;border-right: 1px solid #000" v-else>
{{firstItem.name}}</td>
<td style="width: 60%;border-right: 1px solid #000;">
<table style="width: 100%;border-collapse: collapse;" cellpadding="0" cellspacing="0" >
<tr v-for="(secondItem,thirdIndex) in firstItem.children" style="text-align: center;" :key="thirdIndex">
<td v-if="item.children.length-1 === index && firstItem.children.length-1===thirdIndex">
{{secondItem.name}}</td>
<td v-else style="border-bottom: 1px solid #000;">
{{secondItem.name}}</td>
</tr>
</table>
</td>
<td style="width: 10%;">
<table style="width: 100%;border-collapse: collapse;" cellpadding="0" cellspacing="0">
<tr v-for="(secondItem,thirdIndex) in firstItem.children" style="text-align: center;":key="thirdIndex">
<td v-if="item.children.length-1 === index && firstItem.children.length-1===thirdIndex">
{{secondItem.score}}分</td>
<td v-else style="border-bottom: 1px solid #000;">
{{secondItem.score}}分</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
5、大功告成了,困扰了几天。看不懂的评论,一一解答。