likes
comments
collection
share

el-tree 踩过的坑 !!!

作者站长头像
站长
· 阅读数 32

el-tree 相信前端的家人们都用过,最近维护公司的一个陈年老项目,遇到一个让我印象蛮深刻的 bug,是关于el-tree的,下面是我遇到的问题以及整个调试过程。

业务功能需求是这样的:要实现一个带复选框的树组件,并且该树组件带节点过滤功能,父子节点需要关联,也就是勾选父节点,该父节点下的子节点需要同步勾选,取消勾选亦是。乍一看好像没什么难的,于是乎打开 element-ui 官网,找到一个相似度高的示例<节点过滤>,直接代码 copy 过来,代码如下:

<template>
  <div>
    <el-input
      placeholder="输入关键字进行过滤"
      v-model="filterText">
    </el-input>

    <el-tree
      class="filter-tree"
      :data="data"
      :props="defaultProps"
      default-expand-all
      :show-checkbox="true"
      :filter-node-method="filterNode"
      ref="tree">
    </el-tree>
  </div>
</template>

<script>
  export default {
    watch: {
      filterText(val) {
        this.$refs.tree.filter(val);
      }
    },

    methods: {
      filterNode(value, data) {
        if (!value) return true;
        return data.label.indexOf(value) !== -1;
      }
    },

    data() {
      return {
        filterText: '',
        data: [{
          id: 1,
          label: '一级 1',
          children: [{
            id: 4,
            label: '二级 1-1',
            children: [{
              id: 9,
              label: '三级 1-1-1'
            }, {
              id: 10,
              label: '三级 1-1-2' 
            }, {
              id: 110,
              label: '三级 1-1-3'
            }]
          }]
        }, {
          id: 2,
          label: '一级 2',
          children: [{
            id: 5,
            label: '二级 2-1'
          }, {
            id: 6,
            label: '二级 2-2'
          }]
        }, {
          id: 3,
          label: '一级 3',
          children: [{
            id: 7,
            label: '二级 3-1'
          }, {
            id: 8,
            label: '二级 3-2'
          }]
        }],
        defaultProps: {
          children: 'children',
          label: 'label'
        }
      };
    }
  };
</script>

以上就得到了大致需要的功能,就差一个复选框,然后再加上 show-checkbox属性和check方法,以为这样就万事大吉了。但是自己测试的时候发现,好家伙,还藏了个bug~是什么呢?

handleCheckChange(data, checked) {
 console.log('handleCheckChange', data, checked);
},
handleCheck(data, isCheck) {
 console.log('handleCheck', data, isCheck);
}

此时如果正常的进行勾一个选父节点(一级 1),然后控制台查看打印结果,如下:

el-tree 踩过的坑 !!!

单独测试节点过滤功能也是没有问题~~

最后一步测试问题来了,如果节点过滤后再进行勾选父节点呢,此时子节点会全部选中,相当于失去了节点过滤效果。 如在搜索框中输入“二级”,界面渲染的内容是没有什么问题,然后勾选一个父节点“一级 1”,此时控制台打印的结果却是出于意料。

el-tree 踩过的坑 !!!

我还以为是浏览器缓存的问题,或者是上次操作打印的结果,刷新刷新,重复上一步操作,再看控制台,打印的依旧是这样的结果,看来情况不大妙啊。此时再清空搜索框的内容,发现“一级 1”节点下的所有子节点确是全部选中的,果然不妙,是bug找上门呀,嘤嘤嘤~,怎么会有bug呢,什么鬼。

el-tree 踩过的坑 !!!

既然是节点的过滤,节点的data数据又看不出有什么有用的地方,那么尝试从节点的node数据下手呢?怎样获取到选中节点的node呢?最后在官网寻到一个getNode方法,根据data 或者 key 拿到 Tree 组件中的node

handleCheckChange(data, checked) {
  let node = this.$refs.tree.getNode(data)
  console.log('node', node)
}

handleCheckChange加上以上代码,然后同样的测试方法,搜索框输入二级选中第一个父节点,观察控制台 node的打印结果。

el-tree 踩过的坑 !!!

el-tree 踩过的坑 !!!

el-tree 踩过的坑 !!!

从打印结果来看,观察到有个visible的属性,节点筛选后显示和未显示的节点该属性分别是 truefalse,那么以此为突破口,可以通过该属性值去判断是否需要去手动改变nodechecked属性值就好了。

handleCheckChange(data, checked) {
  let node = this.$refs.tree.getNode(data)
  console.log('node', node)
  if(!node.visible) {
      node.checked = false
  }
}

el-tree 踩过的坑 !!! 搜索框清空后查看界面,任是想要的效果。到此终于解决了这个bug,暗自窃喜三秒钟。

el-tree 踩过的坑 !!!

以上就是我一个前端菜鸟关于el-tree组件,遇到的一个不大不小的坑,以及笨拙的解bug思路。整个调试流程都有截图,一(you)目(dian)了(luo)然(suo),希望对屏幕前的你有所帮助。如有你踩过的其它坑,或者关于以上有更好的解bug思路和办法,或者关于以上有什么不明白的地方,欢迎评论区留言讨论哟~~~

转载自:https://juejin.cn/post/7044896128281608229
评论
请登录