前提
我的代码中树形组件是放在了iview的modal中,iview的modal中v-model对应值的变化是对iview进行v-show,由于这个原因产生了我遇到的下面一系列问题。 ps:一开始我用的是iview的tree,但是它没有搜索功能 基本的结构:
v-model="modal"
title=""
@on-ok="okk"
@on-cancel="cancel"
@on-visible-change="onVisibleChange"
:mask-closable="false"
:closable="false"
>
<Spin fix v-if="showSpin"></Spin>
<Input
v-model="filterText"
placeholder="请输入名称搜索"
clearable
>
</Input>
<el-tree
v-if="modal"
:data="treeData"
:props="defaultProps"
:highlight-current="true"
show-checkbox
check-strictly
node-key="id"
:filter-node-method="filterNode"
ref="tree"
@check="onCheck"
></el-tree>
</Modal>
第一个问题:回显问题
由于后端给的树数据是全部的层级,且树数据不常改动,所以我就没有使用懒加载,直接在created中请求了一次数据
<el-tree
v-if="modal"
:data="treeData"
:props="defaultProps"
show-checkbox
></el-tree>
data(){
return{
defaultProps: {
label:'name'
},
}
}
在prop中获取父组件传来的id
props:{
id:{
type:String,
default: ''
}
}
setCheckedKeys设置默认选择
先上elemenui tree中对此方法的解释
tree组件检测弹窗model的变化使用iview modal的
@on-visible-change
写在nextTick是为了等待tree渲染完毕之后,才能将这个默认值挂上。哦对,还需要等data都取到哦
由于可能父组件传入的id为空字符串,也就是这组数据之前并没有设置过id,所以要将默认选择置空,也就是传给setCheckedKeys一个空数组
到此实现了数据回显
setCurrentKey:function (key){
this.$nextTick(()=>{
this.$refs.tree.setCheckedKeys(key?[key]:[]);
})
}
回显的id对应节点不是第一层的话,上层级节点不自动展开
这个问题的出现 我不知道是不是我的其他写法有问题,还是因为tree所在的modal组件是v-show的原因
通过this.$refs.tree.getNode(key)取到当前需要回显的节点node,打印出来发现有一个parent字段,对应其父节点,所以我就想到直接手动给它的父节点们展开(node有个expaned属性,表示它的展开状态)
setCurrentKey:function (key){
this.$nextTick(()=>{
this.$refs.tree.setCheckedKeys(key?[key]:[]);
key?this.expandParent(this.$refs.tree.getNode(key)):""
})
}
expandParent:function (node){
if (node.parent&&node.parent.level>0){//第一层就不用展开其父节点啦
node.parent.expanded = true;
this.expandParent(node.parent);//递归一下
}
},
让tree为单选
1、设置check-strictly,使其节点父子不相关,上官网解释:
2、监听选择事件,重新setCheckedNodes,让数组参数只有当前选择的节点
onCheck: function (node){
this.$refs.tree.setCheckedNodes([node])
},
再次打开,上次展开的节点依旧在展开着
1、最开始,我是选择监听展开状态存下展开的节点,在关闭的时候一次清除他的expanded
nodeExpand(object,node,element){
this.expand[node.id] = node;
},
close(){
for(let key in this.expand){
this.expand[key].expanded=false
}
this.expand={};
}
它成功了!!!
但是当我使用搜索功能的时候,它会自动展开搜索到的节点,此时并不能用上面的方法监听到展开的节点,并清除,所以下次打开仍然是打开着的。
看到其他有使用
this.$refs.tree.store
来遍历所有的节点设置其expanded
2、后来我选择一个粗暴的方法 给tree增加一个v-if 让他重新渲染,值为modal的v-model值,弹窗打开它就重新渲染,请求tree的数据仍在modal的created中,请求一次。 检测modal的model改变 true时,调用之前的回显方法
onVisibleChange: function (val){
if (val){
this.setCurrentKey(this.oldId?this.oldId:null);
}
},
或者不用v-if,而是在每次打开弹窗都请求一次treeData,那么此时,为了正常回显,会显得方法应该在getTreeData之后调用
最后
不知道上面的情况处理合不合适,欢迎大家指正!!