<template> 结构:
<el-tree
ref="tree"
:data="dataList"
show-checkbox
node-key="id"
:render-content="renderContent"
@check="handleCheckChange"
:default-checked-keys="[1]"
default-expand-all
:props="defaultProps"
></el-tree>
data:
data: () => ({
isCheckAll: false, // 是否全选
pickStatus: 1, // 0 空,1 半选,
treeLens: 0, // el-tree 深度
dataList: [], // 要渲染的成el-tree的数组
isFirstPickAll: true, // 是不是第一次点击全选的
defaultProps: { // 渲染el-tree属性参数
children: 'children',
label: (data, node) => data,
},
});
渲染成HTML
通过 jsx 渲染,更加灵活
/**
* 全选 el-tree 节点
* @param {function} h VNode,渲染函数
* @param {Object} node 节点,里面有许多属性,包括data和
store
* @param {Object} data 也可以在这里通过获取数据的属性
(node.label)
* @param {Object} store
* @return {Object} jsx表达式
*/
renderContent(h, { node, data, store }) {
return (
<span style="display:flex;">
<span>
{node.label.name}
</span>
<span style="flex: 0 0 1">{node.label.financialAccountCode}</span>
</span>
)
},
当页面一进来的时候获取选中的状态
/**
* 设置已经选中的项
* @params {Number} sub 类型下标
*/
async setChecked(sub) {
const type = sub || this.defaultType
try {
const pickedIds = await this.getTypeInfo(type) // 请求后端获取选中的id
this.$refs.tree.setCheckedKeys(pickedIds) // 将这些id对应的项 改成勾选状态
this.handleCheckChange() // 这个函数式用于 判断空状态和半选状态,具体如下面代码片段
} catch (error) {
console.log('el-tree 没有完全构建完成')
}
},
用于全选
这里我用了另外的一个独立复选框做全选。
<el-checkbox
v-model="isCheckAll"
@change="pickAll"
:indeterminate="pickStatus == 1"
></el-checkbox>
判断半选状态和空状态
/**
* 判断半选状态和空装填
* @param {Object} data 当前点击的节点数据
* @param {Object} checked 目前el-tree选中的数据(包括未选中的)
* 注意:由于该函数一开始运行,是无法获取选中节点的(即没有参数),所以获取选中节点不应该在这里 通过参数获取,这些参数只能勾选某个节点时才能获得
*/
handleCheckChange(data, checked, indeterminate) {
// 获取选中的节点
const picked = this.$refs.tree.getCheckedNodes()
// 获取半选中节点
this.halfCheckNodes = this.$refs.tree.getHalfCheckedNodes()
this.halfStatus = (picked.length > 0) && (picked.length < this.treeLens - 1) // 注意这里要减去深度遍历中的根节点
// 当选中的节点处于 > 0,并 < 整棵树的深度时候,则开启半选
},
什么时候是空状态?当不处于半选,并且不处于全选的时候就是空。
也就是 indeterminate 为false,并且 checkbox 为不选中
获取树的深度
/**
* 获取数据深度,用于全选时候做判断
* @returns
*/
getTreeLens() {
// 获取根节点
const rootNode = this.$refs.tree && this.$refs.tree.getNode
(this.dataList[0].id).parent
const _this = this
// travelNodes(rootNode)
;(function travelNodes(tmpRoot) {
// 选中该节点
// tmpRoot.checked = true;
_this.treeLens++ // 这里开始计算
// 叶子节点
try {
if (tmpRoot.childNodes.length) {
// 不是叶子节点,递归遍历
const tmpChildNoes = tmpRoot.childNodes
for (let i = 0; i < tmpChildNoes.length; i++) {
travelNodes(tmpChildNoes[i])
}
}
} catch (err) {
console.log('el-tree没有完全渲染完..')
}
})(rootNode)
},
它的原理是:
其实就像普通的复选框,双向绑定的 checkbox,点击就是选中状态。
不过为了还要显示出半选状态,所以要依赖属性indeterminate
。当indeterminate
的值为true
,即半选状态。
用于全选的处理函数
/**
* 全选 el-tree 节点
*/
pickAll() {
this.pickStatus = 0 // 先设置为空状态(为的就是 indeterminate 这个属性为false,才能为选中状态)
// 先判断是不是第一次点击,因为第一次点击,无论处于什么状态 肯定是要全选的
if (this.isFirstPickAll) {
this.$refs.tree.setCheckedNodes(this.dataList) // 设置所有节点为选中状态
this.isFirstPickAll = false
} else { // 第一次以后:
if (this.isCheckAll) { // 那个另外的独立复选框勾选了
this.$refs.tree.setCheckedNodes(this.dataList) // 设置所有节点为选中状态
} else {
this.$refs.tree.setCheckedKeys([]) // 设置所有节点为空状态
}
}
// 最后判断一下状态
this.handleCheckChange();
},
保存设置
<button @click="save">保存</button>
save() {
// 获取选中状态的 key
const pickedKeys = this.$refs.tree.getCheckedKeys()
// 获取半选状态的 key
const halfPickedKeys = this.halfCheckNodes.reduce(
(acc, item) => {
acc.push(item.id)
return acc
},
[],
)
// 拿到选中的key后,然后该干嘛干嘛...
}
组件挂在完成后:
async mounted() {
await this.setChecked() // 设置后端传来的选中的节点
this.getTreeLens() // 获取树的长度
this.handleCheckChange(); // 设置当前状态(半选、全选、空)
},
总结:
<el-checkbox
v-model="isCheckAll"
@change="pickAll"
:indeterminate="halfStatus"
></el-checkbox>
v-model 选中状态,并且
indeterminate
为false
,则该复选框为选中状态,indeterminate
为true
为半选状态,两个都为false
,则空状态
// 获取选中的节点
const picked = this.$refs.tree.getCheckedNodes()
// 获取半选中节点
this.halfCheckNodes = this.$refs.tree.getHalfCheckedNodes()
// 1.通过node获取
// console.log('通过node获取', this.$refs.tree.getCheckedNodes())
// 2.通过key获取
// console.log('通过key获取', this.$refs.tree.getCheckedKeys())
this.$refs.tree.setCheckedKeys(pickedIds) // 将这些id对应的项 改成勾选状态
this.$refs.tree.setCheckedNodes(this.dataList) // 设置所有节点为选中状态
// 获取选中状态的 key
const pickedKeys = this.$refs.tree.getCheckedKeys()
// 获取半选状态的 key
const halfPickedKeys = this.halfCheckNodes.reduce(
(acc, item) => {
acc.push(item.id)
return acc
},
[],
)
网友评论