最近项目中使用了之前没怎么用过的树性控件,也是在好好的重新熟悉了一下这种组件的架构,作为经验,拿出来分享一下,方便以后有小伙伴用到有关树形组件的开发时能做个参考。
<Tree
ref="tree"
:data="rootNodes"
:load-data="loadData"
class="treestyle"
:render="renderContent"
@on-contextmenu="handleContextMenu"
>
</Tree>
通过打印树的属性我们能看到控件内包含的一些方法
除去iview官方提供的三种能够获取数据的get方法之外,我们也能从iview的底层中找到其他函数方法的使用方法,而我个人觉得比较好用的则是flatState这个属性
这个属性其实就是对应的我们当前看到的树的所有数据,因为当前使用的树是异步加载的,所以在比如写有关操作树功能的时候,会出现对rootdata的数据操作的情况,而对于树的某一节点来讲,除非是完全对于节点或者是下级的操作,否则如果对于树的上级进行操作是进行不了的,而这时我们可以通过flatState这个属性进一步的对整个树的上下级结构进行操作,这些都是在官方文档中没有的
我们可以看到在flatState下的对象都包含三个属性,children/parent,node,nodeKey,其中node属性是包含了当前节点的属性,像expand展开,contextmenu右键菜单等,而你打开任意的一个既有上级有存在下级的节点时,就会显示children/parent属性,children是一般是一个数组,有多个下级,而parent则是一个int类型,对应每一个nodekey,nodekey是唯一的,代表每一个节点
假设我们现在要做一个目录树移动的功能,在目录移动完成后,我们要刷新部分的树,而不是重置树的整个结构,使之再重新加载,对于刷新部分树的功能我们就要用现有的node数据去匹配flatState
//传入当前节点node数据的nodekey
refreshTreePid(nodeKey) {
let parent = 0
this.$refs.tree.flatState.forEach((element) => {
if (element.nodeKey == nodeKey) {
parent = element.parent
}
})
let data = this.$refs.tree.flatState[parent].node
//刷新移动后的目录及下级
this.refreshTreeProps(data)
},
如果是对树的某一个节点的id进行定位的话
//查询结构树内,双击进行定位操作
lookData(data) {
this.$Message.loading({
content:'正在定位...',
duration:0
})
data.selected = true
this.$parent.$parent.$parent.$parent.clear()
let part = this.$refs.tree.flatState
let pos = []
pos.push(data.nodeKey)
part.forEach(element => {
if (element.node.id == data.id ) {
let parent = element.parent
while(part[parent].parent != null){
pos.push(part[parent].nodeKey)
parent = part[parent].parent
}
let root = part[parent].node
this.rootNodes.forEach(el => {
if (el.id == root.id) {
let change = el
el.pos = pos
//事件总线传到对应树组件
this.$Bus.emit('change',change)
//init
this.rootNodes = [
{
id: '',
title: 'root',
loading: false,
children: [],
expand: false,
contextmenu: false,
},
]
}
});
}
});
},
//对树的某一节点id进行定位,展开目标位置
treePartChange(change) {
let pos = change.pos
delete change.pos
let child = change.children
for (let index = 0; index < pos.length; index++) {
let num = pos[pos.length - index - 1]
for (let i = 0; i < child.length; i++) {
if (child[i].nodeKey != num) {
child.splice(i, 1)
i = i - 1
}
}
child = child[0].children
}
this.rootNodes[0].children.forEach(async (element) => {
if (element.id == change.id) {
element.expand = change.expand
element.contextmenu = true
let ch = element
let cha = change
for (let index = 0; index < pos.length; index++) {
if (index == pos.length - 1) {
await this.refreshTreeProps(ch)
for (let i = 0; i < ch.children.length; i++) {
if (ch.children[i].id == cha.children[0].id) {
if (ch.children[i].isSource == true) {
ch.children[i].contextmenu = true
this.$refs.tree.handleSelect(
ch.children[i].nodeKey
)
this.$Message.destroy()
} else {
ch.children[i].expand =
cha.children[0].expand
ch.children[i].contextmenu = true
this.$refs.tree.handleSelect(
ch.children[i].nodeKey
)
this.$Message.destroy()
}
}
}
} else {
await this.refreshTreeProps(ch)
for (let i = 0; i < ch.children.length; i++) {
if (ch.children[i].id == cha.children[0].id) {
if (ch.children[i].isSource == true) {
ch.children[i].contextmenu = true
this.$refs.tree.handleSelect(
ch.children[i].nodeKey
)
this.$Message.destroy()
} else {
ch.children[i].expand =
cha.children[0].expand
ch.children[i].contextmenu = true
if (
'children' in ch &&
ch.children[0] != undefined &&
'children' in cha &&
cha.children[0] != undefined
) {
ch = ch.children[i]
cha = cha.children[0]
}
}
}
}
}
}
}
})
}
正是通过这个flatState属性,能够完成很多自定义功能的开发,快速的找到树的结构节点,如果你正在开发有关树形控件的功能,不妨试试