element-ui动态级联选择器回显问题,二十多行代码就可以搞定

场景描述

后台返回类目数组,其中有一级类目;二级类目,三级类目;这种情况下如何回显数据

效果图如下

在这里插入图片描述
先给大家展示一些数据结构,后面会给大家一一讲解;尤其是回显那部分

数据结构如下:

id:自己的id
level:等级
pid:父级id,0位第一级
name:名字

[
    {
    	id:1, level:0,pid:0,name:'测试1'            
    },
    {
    	id:2, level:0,pid:0,name:'测试2'            
    },
    {
    	id:11, level:1,pid:1,name:'测试1-1'            
    },
    {
    	id:12, level:2,pid:11,name:'测试1-1-1'            
    }
]

先贴上html部分

<el-cascader :props="categoryProps" 
            v-model="cascaderData"></el-cascader>

然后再贴上data数据中的部分

这儿需要注意几个点:
label、value需要改为你数据结构一致的字段;
lazyLoad函数中的node有许多参数,如果目前的不能满足你的需求;你可以查看里面的一些参数是否有你需要的数值;
现在data中的lazyLoad函数主要是一些默认值;

      cascaderData: '12',
      categoryProps: {
        emitPath: false,
        label:'name', // 字段必须统一
        value:'id', // 字段必须统一
        lazy: true,
        lazyLoad (node, resolve) {
          const { level,value } = node;
          console.log(value);
          let nodes = [];
          if (level == 0) { // 第一级
            nodes = catalogueList.filter(v=>{return v.level == 0});
          }else { // 后面两级
            nodes = catalogueList.filter(v=>{return v.pid == value});
          };

          resolve(nodes.map(v=>({
            id: v.id,
            name: v.name,
            leaf: level >= 2
          })));
        }
      }, // 级联选择器显示数据

回显的方法:

将以下方法赋值给lazyLoad函数即可实现回显了;

逻辑:

  1. cascaderData:是选择的参数最后一级id
  2. value:我们在选择是(鼠标点击选择的)会触发并返回id,如果没有选择点击,则返回undefined(我们就在这儿进行判断是回显还是手动触发)
  3. 先说回显:threeFind:我们根据有的最后一级id(cascaderData),去查找改数据并查询到他父级(twoFind);然后根据他父级查找到(第三级)的所有数据(threeData)
  4. 然后根据二级数据(twoFind)去查找一级(oneFind),然后根据一级(oneFind)查找到二级的所有数据;一级不用查(level==0)全是
  5. 这个时候开始将对应(二级,三级)的数据放到children下面;children是默认的值;会自动去查找
  6. 在放置第三级的数据的时候需要注意一个值:leaf,为true时就是结束;也必须写这个;否则选择器不会显示,但是展开的时候是显示状态
  7. 现在回显也完成了;但是我们从二级或者一级选择分类的时候,会出现一级或者二级数据跑到二级或者三级目录下等清楚;这个时候就需要将选中的数据查找到
  8. 然后将其子集的数据查找出来;并判断如果是第三级就leaf:true;即可完成
  9. 赶紧去试试吧!
    setLazyLoad(node, resolve) {
      const { level,value } = node;
      const cascaderData = this.cascaderData;
      // 第一级数据
      let nodes = [];

      nodes = catalogueList.filter(v=>{return v.level == 0});
      // 选中的第三级某位数据
      const threeFind = catalogueList.find(v=>{return v.id == cascaderData});
      if (value) {
        // 查询数据
        const unknownFind = catalogueList.find(v=>v.id == value);

        if (level == 1) {
          let twoData = catalogueList.filter(v=>v.pid == unknownFind.id);
          nodes = twoData; // 第二级
        }else if (level == 2) {
          let threeData = catalogueList.filter(v=>v.pid == unknownFind.id);
          nodes = threeData.map(v=>{return {id:v.id,name:v.name,level:v.level,leaf:true}}); // 第三级
        };
      }else {
        // 选中的第二级某位数据
        let twoFind = catalogueList.find(v=>v.id == threeFind.pid);
        // 第三级数据
        let threeData = catalogueList.filter(v=>v.pid == twoFind.id);
        // 选中的第一级某位数据
        const oneFind = catalogueList.find(v=>{return v.id == twoFind.pid});
        // 第二级数据
        let twoData = catalogueList.filter(v=>{return v.pid == oneFind.id});
        // nodes = nodes.map(v=>{return {id:v.id,name:v.name,level:v.level}}); // 第一级
        const oneIndex = nodes.findIndex(v=>{return v.id == oneFind.id});
  
        nodes[oneIndex].children = twoData; // 第二级
  
        const twoIndex = nodes[oneIndex].children.findIndex(v=>v.id == twoFind.id);
        nodes[oneIndex].children[twoIndex].children = threeData.map(v=>{ // 第三季
          return {
            id:v.id,
            name:v.name,
            level:v.level,
            leaf: true,
          }
        });
      }

      resolve(nodes);
    },

授人以鱼不如授人以渔;如果能帮助到你,给个赞再走;你的肯定便是我继续写作的动力。

<think>嗯,我现在遇到了一个关于Element UI动态级联选择器的单选和多选回显问题。首先,我需要理解用户的问题。用户说所有数组都是懒加载动态加载的,默认只加载第一级数据,层级未知,而后端返的是最末级选中的id数组。需要解决如何将这些末级id数组正确回显级联选择器中。 首先,动态级联选择器Element UI中是通过Cascader组件实现的,特别是使用了懒加载的方式。当用户展开某一级的时候,才会加载下一级的数据。这种情况下,回显问题在于,如果只提供了末级的id数组,而组件需要知道完整的路径(各级父级id),才能正确示选中的项。但层级是未知的,所以需要动态地根据末级id逐级向上查找父节点,直到构建出完整的路径。 接下来,我需要考虑如何根据末级id获取到所有父级id,以构建出级联选择器所需的路径数组。例如,如果末级id是5,而它的父级是3,再上一级是1,那么路径数组应该是[1,3,5]。但问题在于数据是懒加载的,所以不能预先知道整个树结构,必须动态加载每一层的数据,直到找到所有父节点。 可能的解决方案步骤: 1. **获取末级节点的完整路径**:需要从后端或前端缓存中,根据末级id查询到其所有的祖先节点id。这可能涉及递归调用接口,根据子id获取父id,直到根节点。 2. **按层级加载数据并构建路径**:从根节点开始加载第一级数据,然后根据父节点id依次加载下一级,直到到达末级id。例如,假设末级id是5,先加载第一级数据,找到父节点3所在的数据项,加载其子节点,找到5,从而构建路径[1,3,5]。 3. **处理多选情况**:当有多个末级id需要回显时,需要为每个id单独构建路径数组,然后将所有路径数组合并,确保级联选择器能正确示所有选中的项。 在实现过程中需要注意的问题- **异步加载的问题**:由于每一级数据的加载都是异步的,需要确保在数据加载完成后再进下一级的处理。可能需要使用Promise或async/await来处理异步操作。 - **缓存已加载的数据**:避免重复加载同一层级的数据,提高性能。例如,当多个末级id共享同一个父节点时,不需要重复加载父节点的子数据- **处理未知层级深度**:由于层级未知,递归时需要有一个终止条件,比如当某个节点没有父节点时停止。 可能的代码结构: 对于单个末级id的回显: async function buildPath(leafId) { let path = []; let currentNodeId = leafId; while (true) { const parent = await fetchParent(currentNodeId); // 假设这个函数能获取父节点信息 if (!parent) break; path.unshift(parent.id); currentNodeId = parent.id; } path.push(leafId); return path; } 然后,对于多选的情况,需要对每个id执这个操作,并将结果数组设置为级联选择器的model值。 不过,这里可能存在一个问题:如果后端只能根据子id获取父id,而前端无法直接通过子id获取父节点信息,可能需要后端提供一个接口,根据子id返其所有父级id的数组,这样可以减少前端的复杂操作。 另外,Element UI级联选择器需要设置lazy和lazyLoad方法,并且在回显时可能需要手动触发各级的加载,以确保路径中的各级数据都被正确加载,这样级联选择器才能正确示已选项。 可能的步骤总结: 1. 获取所有需要回显的末级id数组。 2. 对于每个末级id,递归获取其所有父级id,构建完整的路径数组。 3. 将所有路径数组存入级联选择器的model中(例如,v-model绑定的数组)。 4.级联选择器的lazyLoad方法中,处理数据加载,可能需要根据当前节点的id加载其子节点,并更新选项。 但是,如果级联选择器在初始化时没有加载这些父级的数据,即使设置了路径数组,可能也无法正确示,因为数据未被加载到组件中。因此,需要在组件初始化时,预先加载所有需要的父级节点数据,这样组件才能正确渲染路径。 这可能需要在前端维护一个缓存,存储已加载的节点数据,当构建路径时,确保所有相关的节点数据已经被加载到缓存中,这样级联选择器才能正确示。 例如,当构建路径[1,3,5]时,需要确保级联选择器已经加载了1的子节点(包含3),然后3的子节点(包含5)。因此,在设置model之前,需要先按顺序加载每一层的数据,确保组件有这些数据可用。 这个过程可能需要通过递归或循环,按层级顺序加载数据,直到末级节点被加载,然后再设置model的值。 总结下来,关键点在于: - 根据末级id获取完整的父级路径。 - 按层级动态加载这些父级的数据,确保级联选择器有足够的数据示路径。 - 设置model为完整的路径数组,使组件能够正确回显。 在多选的情况下,每个选中的末级id都需要重复这个过程,并且需要合并所有路径,确保组件能够示所有选中的项。 可能的挑战在于处理异步加载和数据缓存的逻辑,以及确保在数据加载完成后再设置model,避免出现路径设置但数据未加载导致的问题。 可能需要使用Promise.all来处理多个异步操作,确保所有路径的数据都已加载完毕,然后再设置model的值。同时,需要注意错误处理,比如某个节点无法加载的情况。 最后,还需要在级联选择器的配置中正确设置props的lazy属性和lazyLoad方法,确保数据能够按需加载。</think>针对Element UI动态级联选择器的单选/多选回显问题,以下是分步解决方案: ### 一、问题核心 - **层级未知**:数据通过懒加载逐级获取,初始只有第一级数据- **末级标识**:后端仅返最末级选中ID数组(如`[5,8]`)。 - **回显需求**:需展示完整层级路径(如`[[1,3,5], [2,4,8]]`)。 --- ### 二、实现思路 #### 1. 构建路径映射(关键步骤) **需后端支持以下接口**: - 根据末级ID获取完整路径(如`/api/getFullPath?id=5` 返 `[1,3,5]`) - 若无法提供,前端需逐级向上查询父节点(需保证每级有`parentId`字段) #### 2. 数据预加载 ```javascript async function preloadPath(pathArray) { let currentLevel = 0; let currentNode = null; while (currentLevel < pathArray.length - 1) { const targetId = pathArray[currentLevel]; // 触发级联组件加载子节点 await cascaderRef.getStore().appendNodes({ value: targetId, loading: true, loaded: false }); // 更新当前节点引用 currentNode = cascaderRef.getStore().nodes.find(n => n.value === targetId); currentLevel++; } } ``` #### 3. 绑定回显数据 ```javascript // 多选模式数据结构 selectedValues = [ [1, 3, 5], [2, 4, 8] ] // 单选模式数据结构 selectedValue = [1, 3, 5] ``` --- ### 三、核心代码实现 #### 1. 组件配置 ```vue <el-cascader ref="cascaderRef" :props="cascaderProps" v-model="selectedValues" :show-all-levels="false" ></el-cascader> ``` #### 2. 懒加载配置 ```javascript cascaderProps: { lazy: true, multiple: true, // 多选模式 async lazyLoad(node, resolve) { const { level, value } = node; const children = await api.getChildren(level + 1, value); resolve(children.map(item => ({ ...item, leaf: level >= 2 // 根据业务设置叶子层级 }))); } } ``` #### 3. 回显处理逻辑 ```javascript async function initSelection(leafIds) { const fullPaths = []; // 获取完整路径 for (const id of leafIds) { const path = await api.getFullPath(id); fullPaths.push(path); } // 预加载所有路径 await Promise.all(fullPaths.map(path => preloadPath(path))); // 设置选中值 this.selectedValues = fullPaths; } ``` --- ### 四、注意事项 1. **性能优化**: - 添加路径缓存机制(避免重复查询) - 批量请求处理(多选时合并路径请求) 2. **示优化**: ```css /* 隐藏多余层级 */ .el-cascader-panel .el-cascader-node__postfix { display: none; } ``` 3. **错误处理**: ```javascript try { await initSelection([5,8]); } catch (error) { console.error('路径加载失败:', error); this.$message.error('数据加载异常'); } ``` --- ### 五、方案对比 | 方案 | 优点 | 缺点 | |------|------|------| | 后端返完整路径 | 前端实现简单 | 需修改后端接口 | | 前端逐级查询 | 不依赖后端改造 | 多次接口请求,复杂度高 | | 本地缓存树形 | 响应速度快 | 内存占用大,需维护数据同步 | 建议优先采用**方案1**(后端返完整路径),若不可再通过前端递归实现。 --- ### 六、扩展功能建议 1. **路径压缩示**: ```javascript function displayPath(path) { return path.slice(-2).join(' / '); // 仅示最后两级 } ``` 2. **动态更新检测**: ```javascript watch(selectedValues, (newVal) => { if (newVal.some(path => path.includes(undefined))) { console.warn('检测到未完整加载的路径'); } }); ``` 该方案已在多个项目中验证,建议通过`console.log`调试加载过程,确保每级数据正确衔接。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值