抛出问题
这次要给表格添加选择表头功能,用户自己设置哪些表头要展示,哪些要隐藏。本身功能比较简单,不过因上一篇嵌套表头已经实现了,所以这次的选择表头也要相应处理。
以下代码为vue3,如果开发依赖于vue2的话,更改部分语法即可,大体代码都一致(因部分代码是从我自己项目拷过来的,所以删了很多与当前功能无关的代码,不过应该也能正常运行,如果复制到自己项目不能运行的话可留言)
先来看效果:
这里我的实现方式是:不管有没有嵌套情况,让用户操作的表头总是最后一级的表头
解决思路
无嵌套:表头行是依据传入的columns数组决定的,现在可以默认给数组中每个对象增加hidden
属性代表是否需要隐藏。默认都不需要,等用户操作当前页表格的时候把对应的项hidden
设置为true即可
对于表头嵌套的情况:其实也是给最后一级的项设置hidden
,这里有个问题是怎样找到这一项然后给他设置hidden
属性。比如我把基本情况->是否成年->成年这一项隐藏的话,总不能从开头一直循环循环循环循环来查找。这里我用的方法是获取到columns之后,把每一个最后一级项展开,然后操作完隐藏某些表头项之后再还原。展开的过程中在每一个最后一级的属性中标注它的父label是什么,祖父label是什么等等,方便后面追根溯源
例如:
传入的column为
const compTableOpts = reactive({
key: 'id',
columns: [
{ label: 'ID', value: 'id' },
{ label: '姓名', value: 'name' },
{ label: '爱好', value: 'hobby', headerSlot: 'header3' },
{
label: '基本情况',
children: [
{ label: '性别', value: 'sex' },
{ label: '年龄', value: 'age' },
{
label: '是否成年',
children: [
{ headerSlot: 'header1', value: 'adult', label: '成年' },
{ headerSlot: 'header2', value: 'minor', slotFlag: true, label: '未成年' }
]
}
]
}
]
})
经过展开处理之后为:
对未成年这个表头进行隐藏处理之后:
实现方法
这里我把展开还原数组操作抽取出来,里面每个方法有大概的解释
import { ref } from 'vue'
export default function useFlatAndRestore() {
const flatArr = ref([])
let changeThIndex = 0
// 对columns进行展开处理,changeThIndex其实是parent几,columns每一项如果有父级的话都是从parent1开始
function flatColumns(columns) {
columns.forEach(item => {
changeThIndex = 0
flatChildren(item)
})
}
// 判断当前项是否有children,有的话给他的子级都加上parent几:当前项的label这个属性。对数组展开之后的结果保存在flatArr中
function flatChildren(item, parent) {
if (parent) {
item[`parent${changeThIndex}`] = parent.label
Object.keys(parent).forEach(k => {
if (k.indexOf('parent') !== -1) item[k] = parent[k]
})
}
if (item.children) {
changeThIndex = changeThIndex + 1
item.children.forEach(t => {
flatChildren(t, item)
})
changeThIndex = changeThIndex - 1
return
}
flatArr.value.push(item)
}
// 重置flatArr
function resetFlatArr() {
flatArr.value = []
}
const restoreArr = ref([])
// 对展开的数组进行还原操作,如果当前项没有以parent开头的属性,代表它没有父级。最终结果保存在restoreArr中
function restoreColumns(newList) {
newList.forEach(item => {
const keys = Object.keys(item)
if (keys.every(t => t.indexOf('parent') === -1)) {
restoreArr.value.push(item)
return
}
restoreParent(restoreArr.value, item)
})
}
let i = 0
let temData = {}
// 判断要在数组的哪一项中的children进行push操作,比如:某一项的parent1为'基本情况',则要在'基本情况'的children中push这一项,以此类推
function restoreParent(arr, item) {
i = i + 1
let flag
arr.forEach(t => {
if (t.label === item[`parent${i}`]) {
flag = true
temData = t
}
})
if (!item[`parent${i}`]) {
arr.push(item)
return
}
if (!flag) {
const obj = {
label: item[`parent${i}`],
children: []
}
restoreParent(obj.children, item)
arr.push(obj)
} else {
restoreParent(temData.children, item)
}
i = 0
temData = {}
}
// 重置restoreArr
function resetRestoreArr() {
restoreArr.value = []
}
return {
flatColumns,
flatArr,
restoreColumns,
restoreArr,
resetRestoreArr,
resetFlatArr
}
}