element级联选择器懒加载 单选和多选 回显解决方法

**问题:

项目需求是 级联选择器懒加载, 并且级联选择器有单选的回显和多选的回显, 一开始 单选还觉得挺容易, 但是多选 就 花了些时间研究才做出了.特地记录一下,因为没有看到讲的比较清楚的**

单选的回显:

注意点:
(1) 单选回显只需要绑定 回显的 id 即可, 会自动根据id发起异步请求
(2) 回显id 要是 一条链, 就是 当前节点di和这个节点所有父级id, 一个数组,如[‘1’,‘2’]
(3) 要触发自动发起异步请求, 需要第一次懒加载中是异步获取数据
(4) 不需要绑定 options 给级联选择器
(5) 手动添加了children属性, 添加过程也会触发懒加载,导致子级数据重复, 这时我们要判断 如有 chidlren属性了就不要进行加载哦.

栗子代码:
xx.vue文件,自行复制测试哈, 关键代码就懒加载那里, 其他是模拟数据.关键代码复制使用就行了,请求方法换成自己的.
先看效果:
在这里插入图片描述

<!--
 * @Author: wuwle
 * @Date: 2020-09-06 23:07:05
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2021-10-09 19:22:23
 * @FilePath: \demo\vue\vue基础\vue-cli\pro_02\src\views\About.vue
-->
<template>
  <div class="home">
    <el-cascader
      :props="props"
      clearable
      v-model="list"
      ref="cdd"
    ></el-cascader>
    {{ list }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      list: ["2", "5"], // 回显的id
      // list: [],
      props: {
        // multiple: true,
        checkStrictly: true, // 父子不想关联
        // emitPath: false,
        lazy: true,
        lazyLoad: this.lazyLoads,
      },
    };
  },

  methods: {
      // 懒加载
    async lazyLoads(node, resolve) {
      if (node.level == 0) {
        let res = await this.getfristChild(); // 不存在就默认加载第一集节点
        resolve(res);
      } else {
        // 有children属性了就不要再请求了,不然字节点会重复
        if (!node.data.children) {
          // 获取子节点数据
          let res = await this.getOther(node.data.value);
          setTimeout(() => {
            resolve(res);
          }, 200);
        } else {
          resolve([]);
        }
      }
    },
    // 模拟请求一级节点
    async getfristChild() {
      return [
        {
          label: "第一个",
          hasChdild: true,
          pid: null,
          value: "1",
        },
        {
          label: "第2个",
          hasChdild: true,
          pid: null,
          value: "2",
        },
        {
          label: "第3个",
          hasChdild: true,
          pid: null,
          value: "3",
        },
      ];
    },
    // 模拟请求子级节点
    async getOther(value) {
      let res = [];
      if (value == 1) {
        res = [
          {
            label: "第一个1",
            hasChdild: false,
            pid: 1,
            value: "3",
          },
          {
            label: "第一个2",
            hasChdild: false,
            pid: 1,
            value: "4",
          },
        ];
      }
      if (value == 2) {
        res = [
          {
            label: "第2个1",
            hasChdild: false,
            pid: 2,
            value: "5",
          },
          {
            label: "第2个2",
            hasChdild: false,
            pid: 2,
            value: "6",
          },
        ];
      }
      return res;
    },
  },
};
</script>

多选的回显:

注意点:
(1) 多选要绑定 options 给级联选择器 作为第一次的数据
(2) 回显id 要是 一条链, 就是 当前节点di和这个节点所有父级id, 一个二维数组,如[‘1’,[‘2’,‘5’]]
(3) 实现原理是:
懒加载数据是通过children属性添加的,也就是一般我们获取了一级数据, 点击一级数据懒加载子级数据, 子级数据加载回来是放在一级数据的children属性下的, 那么, 我们为了回显, 我们第一次就手动根据 回显 id 拿 子级数据,添加到chdilren属性下,这样就可以回显了

(4) 当回显后去点击有子级数据的懒加载时, 会发现懒加载后 回显内容丢失, 这时要在懒加载时记录加载器回显id, 加载后还原回来.
(5) 手动添加了children属性, 添加过程也会触发懒加载,导致子级数据重复, 这时我们要判断 如有 chidlren属性了就不要进行加载哦.

栗子代码:
xx.vue文件,自行复制测试哈, 关键代码就懒加载那里, 其他是模拟数据.关键代码复制使用就行了,请求方法换成自己的.
先看效果:
在这里插入图片描述

2021-11-17更新
根据评论反馈设置父子节点相关联就会回显失败,经过测试,确实是,目前已经更新,通用了,改动不大,主要加了叶子节点判断,整体思路一样的。

<!--
 * @Author: wuwle
 * @Date: 2020-09-06 23:07:05
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2021-10-09 19:36:36
 * @FilePath: \demo\vue\vue基础\vue-cli\pro_02\src\views\About.vue
-->
<template>
  <div class="home">
    <el-cascader :props="props"
                 clearable
                 v-model="list"
                 ref="cdd"
                 :options="optionsList"></el-cascader>
    回显id:{{list}}
  </div>
</template>

<script>
export default {
  data() {
    return {
      list: [["1", "11", "111"], ["3"]], // 回显id, 要求是真个节点链, 父级id都要有
      // list: [],
      props: {
        multiple: true,
        checkStrictly: true, // 父子相关联
        // emitPath: false,
        lazy: true,
        lazyLoad: this.lazyLoads,
        leaf: "leaf", // 需要指定叶子节点,不然显示有问题
      },
      optionsList: [],
      isShow: false,
    };
  },
  mounted() {},

  methods: {
    async lazyLoads(node, resolve) {
      console.log(node);
      if (node.level == 0) {
        if (this.list.length > 0) {
          // 存在回显的id我们才去设置回显
          let res = await this.format(); // 这里就是获取第一次要回显的内容了
          console.log("00000", res);
          this.optionsList = res; // 有回显第一次就直接给绑定的对象,不要resolve
        } else {
          let res = await this.getfristChild(); // 不存在就默认加载第一集节点
          resolve(res);
        }
      } else {
        // 记录选择的,不然会点击字节点加载时丢失数据
        let list = this.list;
        // 有children属性了就不要再请求了,不然字节点会重复
        if (!node.data.children) {
          // 获取子节点数据
          let res = await this.getOther(node.data.value);
          setTimeout(() => {
            // 模拟延时,实际不需要
            resolve(res);
          }, 100);
        } else {
          resolve([]);
        }
        // 重新把选择的id放回来-
        // this.$nextTick(() => {
        //   this.list = [...new Set([...this.list, ...list])]; //差别: 合并并且去重
        // });
        setTimeout(() => {
          this.list = [...new Set([...this.list, ...list])]; //差别: 合并并且去重
        }, 250);
      }
    },
    // 模拟请求一级节点
    async getfristChild() {
      return [
        {
          label: "第一个",
          hasChdild: true,
          leaf: false,
          pid: null,
          value: "1",
        },
        {
          label: "第2个",
          hasChdild: true,
          leaf: false,

          pid: null,
          value: "2",
        },
        {
          label: "第3个",
          hasChdild: true,
          leaf: true,

          pid: null,
          value: "3",
        },
      ];
    },
    // 模拟请求子级节点
    async getOther(value) {
      let res = [];
      if (value == 1) {
        res = [
          {
            label: "第一个1",
            hasChdild: false,
            pid: 1,
            value: "11",
            leaf: false, // 差别: 这里加了是否叶子节点属性,后面都加了
          },
          {
            label: "第一个2",
            hasChdild: false,
            pid: 1,
            value: "12",
            leaf: false,
          },
        ];
      }
      if (value == 2) {
        res = [
          {
            label: "第2个1",
            hasChdild: false,
            pid: 2,
            leaf: true,
            value: "5",
          },
          {
            label: "第2个2",
            hasChdild: false,
            leaf: true,

            pid: 2,
            value: "6",
          },
        ];
      }
      if (value == 11) {
        res = [
          {
            label: "第3个1",
            hasChdild: false,
            pid: 2,
            leaf: true,

            value: "111",
          },
          {
            label: "第3个2",
            hasChdild: false,
            leaf: true,

            pid: 2,
            value: "112",
          },
        ];
      }
      return res;
    },
    // 这个方法不变哦
    // 根据回显的id获取 第一次的数据, id必须是 一条链, 就是当前节点到此节点的一级节点的整条链 id 都要有
    async format() {
      let res = await this.getfristChild(); // 拿一级数据
      this.list.forEach((item) => {
        // 遍历回显的id 二维数组
        if (item.length > 1) {
          item.forEach(async (sitem, index) => {
            if (index == item.length - 1) {
              return; // 如果是一级节点就不用查找了
            }
            let arr = await this.getOther(sitem); // 不是一级,获取子级
            findItem(res, arr, sitem); //  判断当前拿到的子级数据属于哪个一级数据下的子级,并且加到当前一级的children属性下
          });
        }
      });
      // 递归判断
      function findItem(res, arr, id) {
        for (let i = 0; i < res.length; i++) {
          if (res[i].value === id) {
            res[i].children = arr; // 有chidlren 也要判断是不是这个children下的子级
            return res;
          }
          if (res[i].children) {
            findItem(res[i].children, arr, id);
          }
        }
      }
      return res;
    },
  },
};
</script>


有问题评论哈

评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值