el-cascader 级联选择器懒加载的使用及回显 + 点击任意一级都能返回

需要实现的需求

  • 数据渲染使用懒加载
  • 点击任意一级都可返回,不需要一直点到最后一级
  • 编辑或者查看功能,回显之前选择的数据

实例解析

dom 元素

<el-cascader
  v-model="value"
  :options="options"
  :props="props"
  :key="num"
  @change="chaangeFunc"
  ref="refHandle"

></el-cascader>
  • value - 级联选择器绑定的数据
  • options - 级联选择器列表数据
  • props - 级联选择器配置内容
  • num - 为级联选择器设置节点,后续在数据变化时,可以更新节点通知 DOM 更新
  • chaangeFunc - 监听级联选择器的选择事件

模拟接口

// 模拟接口数据
// level:层级,key:用上一级查下一级参数使用的标识
getTempData(level, key) {
  return new Promise((resolve, reject) => {
    let result = []; // 最终要返回的数据
    if (level == 1) {
      // 一级的数据
      result = [
        { label: "测试1", value: 1, level: 1 },
        { label: "测试2", value: 2, level: 1 },
      ];
    }
    if (level == 2) {
      // 二级的数据
      if (key == 1) {
      	// "测试1" 查回来的子数据
        result = [
          { label: "测试1-1", value: 11, level: 2 },
          { label: "测试1-2", value: 12, level: 2 },
          { label: "测试1-3", value: 13, level: 2 },
        ];
      }
    }
    if (level == 3) {
      // 二级的数据
      if (key == 11) {
        // "测试1-1" 查回来的子数据
        result = [
          { label: "测试1-1-1", value: 111, level: 3 },
          { label: "测试1-1-2", value: 112, level: 3 },
          { label: "测试1-1-3", value: 113, level: 3 },
        ];
      }
    }
    setTimeout((item, index) => {
      console.log("级联请求到的数据", result);
      // 做一个延时,模拟接口数据返回
      resolve(result);
    }, 1000);
  });
}
// 完整的数据结构
// [{
//   label: "测试1",
//   value: 1,
//   children: [
//     {
//       label: "测试1-1",
//       value: 11,
//       children: [
//         { label: "测试1-1-1", value: 111 },
//         { label: "测试1-1-2", value: 112 },
//         { label: "测试1-1-3", value: 113 },
//       ],
//     },
//     { label: "测试1-2", value: 12 },
//     { label: "测试1-3", value: 13 },
//   ],
// },
// { label: "测试2", value: 2, children: [] },]

渲染数据

  • 默认请求一级数据
// 默认请求一级数据
this.getTempData(1).then((dataLev1) => {
 this.options = dataLev1;
});
  • 级联选择器懒加载函数

checkStrictly
是否严格的遵守父子节点不互相关联
boolean

lazyLoad
加载动态数据的方法,仅在 lazy 为 true 时有效
function(node, resolve),node 为当前点击的节点,resolve 为数据加载完成的回调(必须调用)

props: {
  checkStrictly: true, // 取消父节点与子节点的严格关联,可以任意选中任何一级作为结束
  lazy: true,
  lazyLoad: (node, resolve) => {
    let result = node.data;
    console.log("点击的节点数据", result);
    if (result) {
      if (result.level != 3) {
        // 如果当前点击的不是第三级,则需要去调用接口查询数据
        this.getTempData(Number(result.level) + 1, result.value).then(
          (sourceData) => {
            let data = [];
            if (sourceData && sourceData.length > 0) {
              data = sourceData;
            }
            // 将获取到的数据抛出
            resolve(data);
          }
        );
      } else {
        resolve([]);
      }
    } else {
    }
  },
},
  • 效果
    • 默认渲染一级
      默认渲染一级
    • 点击请求二级
      点击请求二级
    • 再点击请求三级
      再点击请求三级
    • 选中任意一级都能返回
      选中任意一级都能返回
// 如果需要在选中后关闭级联弹层,监听 change 事件即可
chaangeFunc() {
  console.log("触发了change", this.value);
  // 选中节点后,关闭下拉
  this.$refs.refHandle.dropDownVisible = false;
}

数据回显

  • 第一步,获取级联下拉列表的 options,不需要全部渲染,只需要渲染被选中的部分的那一条链路
  • 第二步,为级联选择器绑定的 value 赋值
  • 第三步,为最后一级添加 leaf 属性,告诉结构树此节点为末级节点

this.value

getDetail() {
  let detailList = [1, 11, 111]; // 模拟获取到的需要渲染的节点数据
  this.getTempData(1).then((dataLev1) => {
    this.options = dataLev1;
    console.log("渲染完了一级");
    this.options.map((itemLev1, indexLev1) => {
      if (itemLev1.value == detailList[0]) {
        console.log("匹配到一级选中内容,开始查询二级");
        this.getTempData(2, itemLev1.value).then((dataLev2) => {
          if (dataLev2 && dataLev2.length > 0) {
            console.log("查询到了二级数据,继续向下查询");
            this.$set(itemLev1, "children", dataLev2);
            console.log("渲染完了二级");
            itemLev1.children.map((itemLev2, indexLev2) => {
              if (itemLev2.value == detailList[1]) {
                console.log("匹配到二级选中内容,开始查询三级");
                this.getTempData(3, itemLev2.value).then((dataLev3) => {
                  if (dataLev3 && dataLev3.length > 0) {
                    console.log("查询到了三级数据,即最末为三级");
                    this.$set(itemLev2, "children", dataLev3);
                    itemLev2.children.map((itemLev3, indexLev3) => {
                      console.log("末级添加标志位");
                      itemLev3.leaf = "leaf";
                    });
                  } else {
                    console.log("未查询到三级数据,即最末为二级");
                    itemLev2.leaf = "leaf";
                  }
                  console.log("渲染完了三级");
                  this.value = detailList;
                  this.num += 1;
                });
              }
            });
          } else {
            console.log("未查询到二级数据,即最末为一级");
            itemLev1.leaf = "leaf";
          }
          this.value = detailList;
          this.num += 1;
        });
      }
    });
  });
},
  • 执行渲染数据的方法 getDetail
级联请求到的数据 (2) [{…}, {…}]
渲染完了一级
匹配到一级选中内容,开始查询二级
级联请求到的数据 (3) [{…}, {…}, {…}]
查询到了二级数据,继续向下查询
渲染完了二级
匹配到二级选中内容,开始查询三级
级联请求到的数据 (3) [{…}, {…}, {…}]
查询到了三级数据,即最末为三级
末级添加标志位
渲染完了三级

渲染的过程

完整代码

<template>
  <div class="activeEnroll_list">
    <el-cascader
      v-model="value"
      :options="options"
      :props="props"
      :key="num"
      @change="chaangeFunc"
      ref="refHandle"
    ></el-cascader>
  </div>
</template>

<script>
export default {
  name: "activeEnroll_list",
  components: {},
  data() {
    return {
      num: 0,
      value: [],
      options: [
        // {
        //   label: "测试1",
        //   value: 1,
        //   children: [
        //     {
        //       label: "测试1-1",
        //       value: 11,
        //       children: [
        //         { label: "测试1-1-1", value: 111 },
        //         { label: "测试1-1-2", value: 112 },
        //         { label: "测试1-1-3", value: 113 },
        //       ],
        //     },
        //     { label: "测试1-2", value: 12 },
        //     { label: "测试1-3", value: 13 },
        //   ],
        // },
        // { label: "测试2", value: 2, children: [] },
      ],
      props: {
        checkStrictly: true, // 取消父节点与子节点的严格关联,可以任意选中任何一级作为结束
        lazy: true,
        lazyLoad: (node, resolve) => {
          let result = node.data;
          console.log("点击的节点数据", result);
          if (result) {
            if (result.level != 3) {
              this.getTempData(Number(result.level) + 1, result.value).then(
                (sourceData) => {
                  let data = [];
                  if (sourceData && sourceData.length > 0) {
                    data = sourceData;
                  }
                  resolve(data);
                }
              );
            } else {
              resolve([]);
            }
          } else {
          }
        },
      },
    };
  },

  created() {},

  mounted() {
    let flag = true; // flag 控制是执行新增还是编辑
    if (flag) {
      // 是编辑
      this.getDetail();
    } else {
      // 是新增
      this.getTempData(1).then((dataLev1) => {
        this.options = dataLev1;
      });
    }
  },

  watch: {},
  computed: {},

  methods: {
    chaangeFunc() {
      console.log("触发了change", this.value);
      // 选中节点后,关闭下拉
      this.$refs.refHandle.dropDownVisible = false;
    },
    // mock 接口数据
    getTempData(level, key) {
      return new Promise((resolve, reject) => {
        let result = [];
        if (level == 1) {
          result = [
            { label: "测试1", value: 1, level: 1 },
            { label: "测试2", value: 2, level: 1 },
          ];
        }
        if (level == 2) {
          if (key == 1) {
            result = [
              { label: "测试1-1", value: 11, level: 2 },
              { label: "测试1-2", value: 12, level: 2 },
              { label: "测试1-3", value: 13, level: 2 },
            ];
          }
        }
        if (level == 3) {
          if (key == 11) {
            result = [
              { label: "测试1-1-1", value: 111, level: 3 },
              { label: "测试1-1-2", value: 112, level: 3 },
              { label: "测试1-1-3", value: 113, level: 3 },
            ];
          }
        }
        setTimeout((item, index) => {
          console.log("级联请求到的数据", result);
          resolve(result);
        }, 1000);
      });
    },
    getDetail() {
      let detailList = [1, 11, 111]; // 模拟获取到的需要渲染的节点数据
      this.getTempData(1).then((dataLev1) => {
        this.options = dataLev1;
        console.log("渲染完了一级");
        this.options.map((itemLev1, indexLev1) => {
          if (itemLev1.value == detailList[0]) {
            console.log("匹配到一级选中内容,开始查询二级");
            this.getTempData(2, itemLev1.value).then((dataLev2) => {
              if (dataLev2 && dataLev2.length > 0) {
                console.log("查询到了二级数据,继续向下查询");
                this.$set(itemLev1, "children", dataLev2);
                console.log("渲染完了二级");
                itemLev1.children.map((itemLev2, indexLev2) => {
                  if (itemLev2.value == detailList[1]) {
                    console.log("匹配到二级选中内容,开始查询三级");
                    this.getTempData(3, itemLev2.value).then((dataLev3) => {
                      if (dataLev3 && dataLev3.length > 0) {
                        console.log("查询到了三级数据,即最末为三级");
                        this.$set(itemLev2, "children", dataLev3);
                        itemLev2.children.map((itemLev3, indexLev3) => {
                          console.log("末级添加标志位");
                          itemLev3.leaf = "leaf";
                        });
                      } else {
                        console.log("未查询到三级数据,即最末为二级");
                        itemLev2.leaf = "leaf";
                      }
                      console.log("渲染完了三级");
                      this.value = detailList;
                      this.num += 1;
                    });
                  }
                });
              } else {
                console.log("未查询到二级数据,即最末为一级");
                itemLev1.leaf = "leaf";
              }
              this.value = detailList;
              this.num += 1;
            });
          }
        });
      });
    },
  },
};
</script>
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Cascader 级联选择器懒加载,一般是通过在 `load` 事件中异步加载子选项实现的。当用户选择某一级选项时,会触发 `load` 事件,此时可以根据当前选中的选项,请求后台数据获取下一级选项列表,然后更新 Cascader 的选项列表。 在懒加载时,如果需要回显已选中的选项,可以通过 `lazy` 属性配合 `value` 属性实现。`lazy` 属性表示是否启用懒加载模式,`value` 属性表示级联选择器的选中值,是一个数组。 以下是一个简单的示例: ```html <el-cascader v-model="selectedOptions" :options="options" :lazy="true" :value="selectedOptions" @load="handleLoad" ></el-cascader> ``` 在这个示例中,`selectedOptions` 是一个数组,用于绑定级联选择器的值。`options` 是一个数组,表示级联选择器的选项列表。`lazy` 属性设置为 `true`,表示启用懒加载模式。`value` 属性设置为 `selectedOptions`,表示级联选择器的选中值与 `selectedOptions` 绑定。 当用户选择某一级选项时,会触发 `load` 事件,此时会调用 `handleLoad` 方法,该方法需要异步请求后台数据,获取下一级选项列表,然后更新级联选择器的选项列表。在加载完成后,需要将 `selectedOptions` 设置为对应的数组,以便回显已选中的选项。以下是一个简单的 `handleLoad` 方法示例: ```js methods: { async handleLoad(selectedOptions) { const res = await axios.get('/api/cascader', { params: { selectedOptions: selectedOptions } }) const options = res.data // 更新级联选择器的选项列表 this.$set(selectedOptions[selectedOptions.length - 1], 'children', options) // 回显已选中的选项 this.selectedOptions = [...selectedOptions] } } ``` 在这个示例中,`handleLoad` 方法异步请求后台数据,获取下一级选项列表,然后使用 `$set` 方法更新级联选择器的选项列表,最后将 `selectedOptions` 设置为对应的数组,以便回显已选中的选项。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值