1 、不靠谱的官网示例
首先说我觉得最不靠谱的案例,就是官网的示例,你就说我要子表的实现,你可是官网啊,我要的是子表,而官网倒是清晰简洁,但最致命的问题是没有表头
通过官网代码可知,数据里加了children,然后el-table标签上添加了:tree-props="{children: 'children', hasChildren: 'hasChildren'}" 的属性。但我的需求是子表也要有表头
2 、必须的children子数据
既然官网示例不行,为了快速开发,我希望找到一个更快速的方案或者思路。既然要实现子表,那么这个数据里的children肯定是要有的。
tableData: [{
id: 1,
date: '2022-05-02',
name: '公司1',
address: '北京市海淀区上地五街'
}, {
id: 2,
date: '2022-05-04',
name: '公司2',
address: '北京市海淀区上地六街'
}, {
id: 3,
date: '2022-05-01',
name: '公司3',
address: '北京市海淀区上地七街',
children: [{
id: 31,
性别: '男',
name: '张三',
position: '前端开发'
}, {
id: 32,
性别: '男',
name: '李四',
position: 'java开发'
}, {
id: 33,
性别: '女',
name: '王五',
position: '测试'
}]
}, {
id: 4,
date: '2022-05-03',
name: '公司4',
address: '北京市海淀区上地八街'
}]
3 、开始创建子表,动态插入
既然官网不提供表头,那么我就不能按照官网的实现来做了。是不是可以自己在左侧添加展开闭合的按钮呢,因为初始化的时候子表一定是闭合的。当点击左侧自定义按钮时,我们可以获取到当前父表的索引,在索引加1的地方手动插入一个一个tr 补充td,然后插入子表。而子表自然是要做一个组件啦。看到刚才公司3是有children子表数据的。
插入子表组件:
<div style="display:none;" id="subDataComponent">
<sub-table :subData="subData"></sub-table>
</div>
插入方法:
showSubTable(scope) {
this.subData = scope.row.children || []; // 获取children数据
let index = scope.$index; // 获取当前点击的父表索引
let tableDom = document.querySelector('.el-table__body');
var newTR = tableDom.insertRow(index + 1); // 在点击父表行的下一行插入一个tr
//添加列:序号
var newTD = newTR.insertCell(); // tr中插入td
newTD.setAttribute('colspan', 3); // 控制列数
// 将子表内容动态插入td中
let subDataHTML = document.querySelector('#subDataComponent').innerHTML;
newTD.innerHTML = subDataHTML;
}
子表SubTable.vue内容
<template>
<div class="box-container">
<el-table
:data="newList"
style="width: 100%;margin-bottom: 20px;"
border>
<el-table-column
prop="gender"
label="性别"
width="180">
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="position"
label="职位">
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: ["subData"],
watch: {
subData(newValue) {
this.newList = newValue;
}
},
data () {
return {
newList: []
}
},
methods: {
}
}
</script>
看效果如下图,明明做的没有问题,但是却暂无数据,vue最常出问题的就是组件间的数据传递。但这里却不是,原因是刚刚给子组件传递,subData的数据传递给子组件还没有渲染完成,就开始获取InnerHTML,不会实现。
普通机器执行一行代码需要0.001ms的时间,这个小子组件大概延时50ms是可以的
// 将子表内容动态插入td中
setTimeout(() => {
let subDataHTML = document.querySelector('#subDataComponent').innerHTML;
newTD.innerHTML = subDataHTML;
}, 50)
看一下效果,带表头的子组件出来了
4 、组件化思想插入
但现在不流行InnerHTML了,动不动就讲究组件化,很多人不用组件,写vue不用elementui已经不会开发了,所以想个组件化思路来插入吧。这样依然可以实现,而且不需要在延迟填充了。
给子组件添加ref属性:
<div style="display:none;" id="subDataComponent">
<sub-table :subData="subData" ref="subDataComp"></sub-table>
</div>
插入组件:
// 将子表内容动态插入td中
// setTimeout(() => {
// let subDataHTML = document.querySelector('#subDataComponent').innerHTML;
// newTD.innerHTML = subDataHTML;
// }, 50)
// 组件化思路插入
let subDataRef = this.$refs.subDataComp.$el;
newTD.appendChild(subDataRef);
5、el-table真是一个浑身插槽的东西啊
这一步开始通过插槽的方式,使劲儿往el-table里插入子表,但官网那个例子做的真是烂啊。还是得想办法往进插子el-table。因为一旦用了elementui,你经常会碰见很多稀奇的问题,所以最好的方式就是接着用elementui,很多人如果不用elementui,已经不会写vue了,可咋办啊。
这一步不需要那个子表sub-data组件了,去掉。然后通过插入新的子el-table-column,并且重点是给el-table-column添加 type="expand"属性。并且一定要记住,你插入的这个子表,要写在其他列的前面,否则展开闭合的按钮会跑到后面去。
<el-table
:data="tableData"
style="width: 100%;margin-bottom: 20px;"
border>
<el-table-column props="children" type="expand">
<template slot-scope="scope">
<el-table
:data="scope.row.children">
<el-table-column
prop="gender"
label="性别"
width="180">
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="position"
label="职位">
</el-table-column>
</el-table>
</template>
</el-table-column>
<el-table-column
prop="date"
label="日期"
width="180">
</el-table-column>
<el-table-column
prop="name"
label="公司名"
width="180">
</el-table-column>
<el-table-column
prop="address"
label="地址">
</el-table-column>
</el-table>
6、结语
其实要实现一个需求的方法还是很多的,不一定非要围绕着别人写好的组件,我们来使用,这样除了完成需求,却很难让自己得到提升。写专利不也是一个道理嘛,大家平时都这样做,久而久之都熟悉了,麻木了,却难以发现痛点。而善于发现痛点的那个人,就会有更多的专利思路,实现更优解。有更多的解题思路的小伙伴记得留言哦!!!