本来是不太想动的…

无可奈何,看到一句话【业精于勤, 荒于嬉】便还是动手写一写加深理解的同时给以后的自己留个备份吧…

element-ui Tree组件如何给具有懒加载的tree设置半选效果?这也是让我很头疼的一个问题…

因为数据不是一口气都请求回来的,故而当你进入页面的时候,你有的数据只是你能看到的第一层节点,但是由于某种情况需要做数据的回显,这就会产生问题了。

当然,如果数据不是很多的情况下自然可以获取全部的数据,然后给tree设置上默认选中的节点,这个问题自然也就不存在了。

但,若是数据量庞大且级数很深的情况下,一般接口都会根据前端传给后端的标识来返回某层数据,这样就会产生一个问题:

当你设置了默认选中的子节点,但是由于刚进入页面此时tree中数据暂是没有这个子节点时,其父节点并不会具有半选效果】如下图所示:

element-ui Tree之懒加载叶子节点设置半选效果-风君雪科技博客

我还是一如既往粗鲁的找度娘询问了一番,没有找到想要的结果…

直到我在element-ui的git上翻寻前人智慧时,遇到了Ta

这个大哥给了一个非常棒的想法,并且成功了让心猿意马的我眼前一亮【原来还可以这般巧妙的使用对象的引用?!】

element-ui Tree之懒加载叶子节点设置半选效果-风君雪科技博客

好了,废话不多说了,先看下使用前的代码吧:

(当然下面使用到的这几个属性在官网都有,哪个不懂的看下文档就行了)

<template>
    <div class="lazy-tree">
        <h2>展示:</h2>
        <el-tree
        :props="props"
        :load="loadNode"
        lazy
        node-key="id"
        :default-checked-keys="[1001]"
        show-checkbox>
        </el-tree>
    </div>
</template>

<script>
export default {
  data () {
    return {
      props: {
        label: 'name',
        children: 'zones',
        isLeaf: 'leaf'
      }
    }
  },
  methods: {
    // 动态获取叶子节点的方法
    loadNode (node, resolve) {
      if (node.level === 0) {
        return resolve([{ name: 'region', id: 1000 }])
      }
      if (node.level > 1) return resolve([])

      setTimeout(() => {
        const data = [{
          id: 1001,
          name: 'leaf',
          leaf: true
        }, {
          name: 'zone'
        }]

        resolve(data)
      }, 500)
    }
  }
}
</script>

<style>
.lazy-tree{
    padding: 20px;
     500px;
    height: 500px;
    background-color: #70E2FA;
}
</style>

然后这里是使用后的代码:

(这里我多加了一些方法用于模仿请求接口啥的都不是重点关注的…核心内容还是这个 setHalfCheckedNodes (key)

<template>
    <div class="lazy-tree">
        <h2>展示:</h2>
        <el-tree
        ref="lazyTree"
        :props="props"
        :load="loadNode"
        lazy
        node-key="id"
        :default-checked-keys="defaultCheckedKeys"
        show-checkbox>
        </el-tree>
    </div>
</template>

<script>
export default {
  data () {
    return {
      props: {
        label: 'name',
        children: 'zones',
        isLeaf: 'leaf'
      },
      // 默认选中的节点
      defaultCheckedKeys: []
    }
  },
  mounted () {
    this.getDetails()
  },
  methods: {
    // 动态获取叶子节点的方法
    loadNode (node, resolve) {
      if (node.level === 0) {
        return resolve([{ name: 'region', id: 1000 }])
      }
      if (node.level > 1) return resolve([])

      setTimeout(() => {
        const data = [
          {
            id: 1001,
            name: 'leaf',
            leaf: true
          },
          {
            id: 1002,
            name: 'zone',
            leaf: true
          }
        ]

        resolve(data)
      }, 500)
    },
    // 模拟的详情接口
    detail () {
      return new Promise((resolve, reject) => {
        const data = [{ id: 1001, name: 'leaf', parent: 1000 }]
        resolve(data)
      })
    },
    // 获取回显数据
    async getDetails () {
      const res = await this.detail()
      res.forEach(item => {
        this.defaultCheckedKeys.push(item.id) // 此处应有去重
        this.setHalfCheckedNodes(item.parent)
      })
    },
    // 设置半选状态
    setHalfCheckedNodes (key) {
      const node = this.$refs['lazyTree'].getNode(key)
      if (node) { // 此处应判断当前节点的checked属性是否为true,是则不必半选
        node.indeterminate = true
      }
    }
  }
}
</script>

<style>
.lazy-tree{
    padding: 20px;
     500px;
    height: 500px;
    background-color: #70E2FA;
}
</style>

总结:

这里我只是轻描淡写的用2层的tree大致讲述了如何设置设置半选状态。

但,即使是更深的tree也还是万变不离其宗,用的还是这个方法,只不过判断第二层是否需要设置半选的时候需要再给第一层再设置下半选。

因为,在你展开第二层tree的时候,如果【选中】状态的叶子节点在第三层,由于此时tree上还没有第三层的数据,

所以组件自动计算发现没有需要有半选和全选的按钮,就会清空你设置好的半选状态。

另外,在 setHalfCheckedNodes 中我说的需要判断当前node的isChecked指的就是下图中的【节点本身是否被选中】

element-ui Tree之懒加载叶子节点设置半选效果-风君雪科技博客