vue 中 element-ui Tree树形控件的使用

2,191 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 7 天,点击查看活动详情

START

  • 最近遇到需要使用树形结构的场景,挺头大的,因为对这方面的API,并不熟悉,现在功能做完了,基本的 API都熟悉了,写个文档,记录一下,基本的用法,方便以后再有这种需求,上手就来。
  • 写这个案例,请先自己创建vue项目,[安装elememt-ui]

一.来个简单的demo

  • 啥都不知道,那就先复制一个官网案例去玩一玩,体会一下。

  • 上代码

    <template>
      <div>
           <!-- 
          data   用来展示数据
          props  树状图配置
                 label   	指定节点标签为节点对象的某个属性值
                 children	指定子树为节点对象的某个属性值
                 disabled	指定节点选择框是否禁用为节点对象的某个属性值
                 isLeaf	  指定节点是否为叶子节点,仅在指定了 lazy 属性的情况下生效  (就是设置这个节点是否有右箭头,懒加载模式下才有)
          @node-click 节点的点击事件
      -->
        <el-tree :data="data" :props="defaultProps" @node-click="handleNodeClick"></el-tree>
      </div>
    </template>
    
    <script>
    export default {
      name: "tree1",
      data() {
        return {
          data: [
            {
              label: "一级 1",
              children: [
                {
                  label: "二级 1-1",
                  children: [
                    {
                      label: "三级 1-1-1",
                    },
                  ],
                },
              ],
            },
            {
              label: "一级 2",
              children: [
                {
                  label: "二级 2-1",
                  children: [
                    {
                      label: "三级 2-1-1",
                    },
                  ],
                },
                {
                  label: "二级 2-2",
                  children: [
                    {
                      label: "三级 2-2-1",
                    },
                  ],
                },
              ],
            },
            {
              label: "一级 3",
              children: [
                {
                  label: "二级 3-1",
                  children: [
                    {
                      label: "三级 3-1-1",
                    },
                  ],
                },
                {
                  label: "二级 3-2",
                  children: [
                    {
                      label: "三级 3-2-1",
                    },
                  ],
                },
              ],
            },
          ],
          defaultProps: {
            children: "children",
            label: "label",
          },
        };
      },
      methods: {
        handleNodeClick(data) {
          console.log(data);
        },
      },
    };
    </script>
    
    
    <style scoped>
    </style>
    
  • 参数解释

    • data 用来展示数据

    • props 树状图配置 这个很重要!!!

      • label 指定节点标签为节点对象的某个属性值
      • children 指定子树为节点对象的某个属性值
      • disabled 指定节点选择框是否禁用为节点对象的某个属性值
      • isLeaf 指定节点是否为叶子节点,仅在指定了 lazy 属性的情况下生效 (就是设置这个节点是否有右箭头,懒加载模式下才有)
    • @node-click 节点的点击事件

  • 效果图

image.png

二.实际项目中去使用

  • 上面的案例,是一个最基本的一个使用案例,它所有的数据都是写好了的,实际项目使用咋做?

实际项目中去使用个人总结

  • 看后端设计返回的数据是什么样的
    • 第一种,只请求一次接口,后端直接把处理好的所有数据返回给我们,就是和上面案例中的data一样,(我遇到的,后端返回的数据层次结构和案例数据有一些不同,需要我们稍加处理,变成和案例数据类似的结构) ==》直接把处理好的数据赋值给data即可
    • 第二种,需要多次请求接口,点击父节点,再去请求子节点的数据。 ==》这里就推荐使用第二种方式,不使用data去赋值,而是使用动态加载节点数据的方法。
  • 我遇到的情况就是两种都有,个人觉的动态加载节点数据的方法,用户体验会更好一些,不过相关API设置有点麻烦。

三.动态加载节点

  • 这个地方官网有两个案例,我这里记录一下我的demo,顺便记录一下,我遇到比较特殊的需求

  • 我自己的demo

    • html代码

      <template>
        <div>
          <h2 style="text-align: center;">树状图动态加载节点案例</h2>
      
          <el-tree
            ref="tree"
            :props="defaultProps"
            :load="loadNode"
            lazy
            :check-strictly="true"
            show-checkbox
            @check-change="checkChange"
            node-key="id"
          ></el-tree>
        </div>
      </template>
      
    • js代码

      export default {
        name: "treelazy",
        data() {
          return {
            defaultProps: {
              children: "children",
              label: "name",
              isLeaf: "leaf",
              // disabled: "hasChild",  //还可以使用disabled控制节点是否能被选择
            },
            selectOrg: {
              orgJsn: {}, //存唯一的值,勾选的
              orgsid: [], //存id,与node-key相结合
            },
          };
        },
        methods: {
          // 树组件动态加载事件
          loadNode(node, resolve) {
            if (node.level === 0) {
              // 这里适合去做数据请求,获取到树状图数据
              // node.level === 0 是初始化树状图最开始就展示的数据
              let res = [
                {
                  id: 6,
                  name: "lazy_tomato集团",
                  children: "",
                },
              ];
              resolve(res);
            } else {
             // 这里适合去做数据请求,获取到树状图数据 (为实现loading效果,添加了定时器)
              setTimeout(() => {
                // 每次请求的数据应该根据node.data.id 去请求(看项目后端需要什么参数,我的是点击节点的id,去获取这个节点下面的子节点数据)
                let res2 = [
                  {
                    id: 10,
                    name: "上海分公司",
                    leaf: false,
                  },
                  {
                    id: 11,
                    name: "武汉分公司",
                    // leaf 这个参数可以根据请求接口,返回的数据信息,去判断这个节点是否还包含子节点,从而控制是否有右箭头
                    leaf: true,
                  },
                ];
                resolve(res2);
              }, 500);
            }
          },
          // 设置复选框为单选的  
          checkChange(data, checked) {
            // 获取当前选择的id在数组中的索引
            const indexs = this.selectOrg.orgsid.indexOf(data.id);
            // 如果不存在数组中,并且数组中已经有一个id并且checked为true的时候,代表不能再次选择。
            if (indexs < 0 && this.selectOrg.orgsid.length === 1 && checked) {
              // 设置已选择的节点为false 很重要
              this.$refs.tree.setChecked(this.selectOrg.orgJsn, false); //设置之前选中的为未选中
              this.selectOrg.orgsid = []; //清空
              this.selectOrg.orgsid.push(data.id); //存唯一的node-key中唯一的标致 id
              this.selectOrg.orgJsn = data; //存当前节点的json
            } else if (this.selectOrg.orgsid.length === 0 && checked) {
              // 发现数组为空 并且是已选择
              // 防止数组有值,首先清空,再push
              this.selectOrg.orgJsn = data;
              this.selectOrg.orgsid = [];
              this.selectOrg.orgsid.push(data.id);
            } else if (
              indexs >= 0 &&
              this.selectOrg.orgsid.length === 1 &&
              !checked
            ) {
              // 再次直接进行赋值为空操作
              this.selectOrg.orgsid = [];
            }
          },
        },
      };
      
    • 样式我就省略了。。

    • 完整的demo,上面代码放一起基本就可以直接运行了

    • 效果图

image.png

3.1控制复选框只能单选

// 设置复选框为单选的  
    checkChange(data, checked) {
      // 获取当前选择的id在数组中的索引
      const indexs = this.selectOrg.orgsid.indexOf(data.id);
      // 如果不存在数组中,并且数组中已经有一个id并且checked为true的时候,代表不能再次选择。
      if (indexs < 0 && this.selectOrg.orgsid.length === 1 && checked) {
        // 设置已选择的节点为false 很重要
        this.$refs.tree.setChecked(this.selectOrg.orgJsn, false); //设置之前选中的为未选中
        this.selectOrg.orgsid = []; //清空
        this.selectOrg.orgsid.push(data.id); //存唯一的node-key中唯一的标致 id
        this.selectOrg.orgJsn = data; //存当前节点的json
      } else if (this.selectOrg.orgsid.length === 0 && checked) {
        // 发现数组为空 并且是已选择
        // 防止数组有值,首先清空,再push
        this.selectOrg.orgJsn = data;
        this.selectOrg.orgsid = [];
        this.selectOrg.orgsid.push(data.id);
      } else if (
        indexs >= 0 &&
        this.selectOrg.orgsid.length === 1 &&
        !checked
      ) {
        // 再次直接进行赋值为空操作
        this.selectOrg.orgsid = [];
      }
    },

3.2 动态加载怎么去做数据请求

//上面代码已经注释好了,哪里去请求

3.3 动态加载如何判断是否有右箭头

 // leaf 这个参数可以根据请求接口,返回的数据信息,去判断这个节点是否还包含子节点,从而控制是否有右箭头
 // 上面代码有 已经注释好了

其他相关

END

  • 暂时就这么多了,后期再补充啦,比心。