javascript
<template>
<div>
<el-table
:data="tableData"
:row-key="rowKey"
:default-expand-all="defaultExpandAll"
:tree-props="treeProps"
>
<!-- 开启树形多选 -->
<el-table-column v-if="showSelection" width="120" align="left">
<template #header>
<el-checkbox
v-model="selectAll"
:checked="selectAll"
:indeterminate="isIndeterminate"
@change="setCheckAll"
/>
{{ selectionName }}
</template>
<template #default="scope">
<el-checkbox
v-model="scope.row[selectionConfig.checked]"
:checked="scope.row[selectionConfig.checked]"
:indeterminate="scope.row[selectionConfig.indeterminate]"
:disabled="scope.row[selectionConfig.disabled]"
@change="setCheck(scope.row)"
/>
</template>
</el-table-column>
<el-table-column prop="name" label="Name" width="180" />
</el-table>
</div>
</template>
<script>
export default {
props: {
// 表格树形数据
// 列配置项
columnConfig: {
type: Array,
default: () => [
{
prop: 'default',
label: '默认',
width: '200',
align: 'center',
ownDefinedFn: () => {
return '默认' // 可返回函数
}
}
]
},
// 数据唯一标识
rowKey: {
type: String,
default: 'id'
},
// 默认展开所有节点
defaultExpandAll: {
type: Boolean,
default: true
},
// 渲染嵌套数据的配置选项
treeProps: {
type: Object,
default: () => ({
children: 'children'
})
},
// 默认开启树形多选框
showSelection: {
type: Boolean,
default: true
},
// 树形多选框标题
selectionName: {
type: String,
default: ''
},
// 多选框配置
selectionConfig: {
type: Object,
default: () => ({
checked: 'checked',
indeterminate: 'indeterminate',
disabled: 'disabled'
})
}
},
data() {
return {
selectAll: false, // 全选
isIndeterminate: false, // 半选
tableData: [
{
id: '1',
name: '目录1',
parentId: '0',
checked: false,
isItemIndeterminate: false,
children: [
{
id: '1-1-1-1',
name: '目录1-1-1-1',
parentId: '1',
checked: false,
isItemIndeterminate: false,
children: []
},
{
id: '1-1-1-2',
name: '目录1-1-1-2',
parentId: '1',
checked: false,
isItemIndeterminate: false,
children: []
}
]
},
{ id: '2', name: '目录2', parentId: '0', checked: false, children: [] },
{ id: '3', name: '目录3', parentId: '0', checked: false, children: [] },
{ id: '4', name: '目录4', parentId: '0', checked: false, children: [] }
]
}
},
methods: {
// 全选
setCheckAll() {
console.log(this.selectAll)
this.tableData.forEach((item) => {
if (!item[this.selectionConfig.disabled]) {
item[this.selectionConfig.checked] = this.selectAll
}
this.setChildren(item, this.selectAll)
})
this.isIndeterminate = false
},
// 单选
setCheck(row) {
// 设置该单元格所有子节点状态
this.setChildren(row, row[this.selectionConfig.checked])
let result = this.setParentCheck(row)
// 遍历到顶级,顶级无父节点,判断顶级节点是否都为选中
if (!result) {
let isAll = this.tableData.every((item) => {
return item[this.selectionConfig.checked]
})
this.selectAll = isAll
if (isAll) {
this.isIndeterminate = false
} else {
let isIndeterminate = this.tableData.some((item) => {
return item[this.selectionConfig.checked] || item[this.selectionConfig.indeterminate]
})
this.isIndeterminate = isIndeterminate
}
}
},
// 设置子节点
setChildren(row, checked) {
row[this.selectionConfig.indeterminate] = false
if (row[this.treeProps.children]) {
row[this.treeProps.children].forEach((item) => {
if (!item[this.selectionConfig.disabled]) {
item[this.selectionConfig.checked] = checked
item[this.selectionConfig.indeterminate] = false
}
if (row[this.treeProps.children]) {
this.setChildren(item, checked)
}
})
}
},
// 设置父节点
setParentCheck(row) {
// 寻找该行数据的父节点
let parent = null
for (let i = 0; i < this.tableData.length; i++) {
parent = this.findItem(this.tableData[i], row.parentId)
if (parent != null) {
break
}
}
// 遍历该行的父节点下,所有的子节点
if (parent != null) {
if (parent[this.treeProps.children]) {
// 子节点是否全都选中,如果是则则勾选该节点
let isAll = parent[this.treeProps.children].every((item) => {
return item[this.selectionConfig.checked]
})
parent[this.selectionConfig.checked] = isAll
if (isAll) {
parent[this.selectionConfig.indeterminate] = false
} else {
let isIndeterminate = parent[this.treeProps.children].some((item) => {
return item[this.selectionConfig.checked]
})
parent[this.selectionConfig.indeterminate] = isIndeterminate
}
// 递归查找该行父级的父级节点
this.setParentCheck(parent, parent[this.selectionConfig.checked])
}
} else {
// 遍历到顶级,停止
return null
}
},
// 查递归找该行的父节点
findItem(row, id) {
if (row.id == id) {
return row
}
if (row[this.treeProps.children]) {
let parent = null
for (let i = 0; i < row[this.treeProps.children].length; i++) {
parent = this.findItem(row[this.treeProps.children][i], id)
if (parent) {
break
}
}
return parent
} else {
return null
}
}
}
}
</script>
<style lang="less" scoped></style>
参考链接
https://blog.csdn.net/weixin_47342392/article/details/139168459
人工智能学习网站