elementui tree的一系列奇怪问题

581 阅读2分钟

前提

我的代码中树形组件是放在了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中对此方法的解释

1646984709(1).png 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,使其节点父子不相关,上官网解释:

1646985340(1).png

2、监听选择事件,重新setCheckedNodes,让数组参数只有当前选择的节点

onCheck: function (node){
  this.$refs.tree.setCheckedNodes([node])
},

1646985515(1).png

再次打开,上次展开的节点依旧在展开着

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之后调用

最后

不知道上面的情况处理合不合适,欢迎大家指正!!