首页IT科技el-cascader默认选中(el-cascader 动态加载选项、编辑时数据回显问题 、单选不加载下一级节点、点击标签选中)

el-cascader默认选中(el-cascader 动态加载选项、编辑时数据回显问题 、单选不加载下一级节点、点击标签选中)

时间2025-08-04 21:48:22分类IT科技浏览7410
导读:网上看了一圈,很多是选项层级固定死3层而不是随意多少层都可以的,还有很多讲不清楚的,填个坑,希望能帮到有缘人。...

网上看了一圈                  ,很多是选项层级固定死3层而不是随意多少层都可以的                        ,还有很多讲不清楚的         ,填个坑              ,希望能帮到有缘人                。

实现该效果                        ,需要后端配合需要提供2个接口:

1.前端传入指定节点ID             ,返回该节点的下一层所有节点ID信息列表                           。

2.前端传入指定节点ID          ,返回该节点从顶部节点至下(到该节点)的所有节点ID列表        。

级联选择器 el-cascader 使用:

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

最关键的只有这两项:v-model绑定值 和 props 配置项

一                  、动态加载选项

props配置:

动态加载选项不需要 :options 配置                         ,静态的才需要            。

props: { checkStrictly: true, //是否可以选择树干节点作为选项 lazy: true, // 是否动态加载子节点 // lazyLoad加载动态数据的方法(仅在 lazy 为 true 时有效) lazyLoad: this.loadTreeNode, },

 远程加载节点的js方法:

//加载树节点 首次加载页面时就会执行一次 loadTreeNode(node, resolve) { console.log(node); // 首次加载时 node为{root:true,level:0} // node 节点数据 获取node的level字段的值 const { level } = node; //下一层节点 const nodes = []; //如果有子节点 或者 为根节点(即首次进入level为0) //也有人写成 node.level == 0 作用是一样的 if (node.hasChildren || node.root) { // 0 代表第一次请求 let nodeId = level == 0 ? null : node.value; //这里setTimeout的目的是 显示加载动画 setTimeout(() => { //调用后端接口 获得返回数据 let ret = this.api(nodeId); if (ret && ret.succeeded) { //ret.reulst为后端返回的数据 let nodes = ret.result; // 回调渲染下一层 resolve(nodes); } else { //后端报错 弹窗提示失败 this.$message({ type: "error", message: "部门层级加载失败                 ,请联系管理员!", }); } }, 1); } else { //如果没有子节点就不发起请求     ,直接渲染                          ,也避免了点击叶子节点仍然有加载动画的问题 resolve(nodes); } },

叶子节点指的是:没有子节点的节点                     ,它就是最底层                           。

这里就需要后端提供第一个接口:

1.前端传入指定节点ID,返回该节点的下一层所有节点ID信息列表(sql查询parentGroupID为指定节点ID的数据即可)            。

返回的数据需要是一个列表                      ,后端返回的数据 List<UserGroupTreeNode> 长这样:

后端的节点定义(可参考):

@Data @AllArgsConstructor @NoArgsConstructor public class UserGroupTreeNode { /** * 节点值 */ private String value; /** * 节点标签 */ private String label; /** * 是否为叶子节点(即没有子节点) true 没有子节点 false 有子节点 */ private Boolean leaf; }

其中value即为节点的ID                         ,label为展示的名称     ,leaf为是否含有子节点                  ,Bool类型        。

value                        ,label         ,leaf 变量名称最好是不要变              ,如果后端提供的变量名是其他名称                        ,前端拿到之后             ,自己转一下也行

二                        、数据回显问题:

在对该条数据点击编辑的时候          ,选择框内需要展示选中的数据                         ,并且点击展开的选项中                 ,也应该选中该条记录     ,效果如下:

这里就需要后端提供第二个接口:

2.前端传入指定节点ID                          ,后端返回该节点从顶部节点至下(到该节点)的所有节点ID列表                           。

格式如下图:

需要特别注意的是顺序

前端拿到它后                     ,复制给 el-cascader 组件v-model绑定的值即可                 。

这里的原理就是,前端在新增功能中                      ,提交数据给后端的时候                         ,v-model绑定的参数的值     ,也是这样的列表形式                  ,所以当绑定值写为这样的列表时                        ,也就能用来回显展示    。

而因为后端一般只存最后一个节点(即选中的节点)的数据         ,我们提交时              ,也只提交最后一个节点的数据.......或者全部提交                        ,让后端去处理                          。

所以需要后端开一个接口             ,查找该接节点之前的各个节点的数据          ,并放入同一个数组返回                         ,前端再将数据直接写回v-model绑定的参数就行了                      。

 这样就处理完成了                 ,但是有一个问题     ,应该算是element-ui的BUG                          ,就是只有在首次加载页面后                     ,编辑数据A时,数据A回显一切正常                      ,关闭弹窗                         ,再编辑其他任何数据时     ,此时弹窗中                  ,el-cascader 组件文本框中                        ,回显都为空。

这个问题         ,最核心的原因是:

首次编辑数据时              ,会根据v-model绑定的参数值                        ,

比如["1","2","3","4"] 这个数组

逐层调用lazyLoad获取整个树结构             ,

即:依次将 "1","2","3","4"作为参数          ,调用lazyLoad                         ,分别渲染头结点"1"                 ,头结点下一层     ,ID为节点"2"的下一层                          ,以及下一层中                     ,ID为“3                ”的下一层,最后整个合并起来                     。

整个过程是组件自动完成的                           。

所以能正确回显    。

但是当关闭编辑弹窗                      ,再编辑其他数据时                         ,虽然el-cascader 组件v-model绑定的参数值发生了变化     ,但是没有再调用lazyLoad方法再逐层请求后端渲染整个结构树                。

所以目前网上的解决办法总体有两种思路:

1.给el-cascader组件绑定 options选项                  ,根据v-model绑定参数的值                        ,也就是数组的值         ,手动调用后端接口              ,逐个获取下一层的选项                        ,拼接成树结构             ,将生成树结构给 el-cascader 使用          ,这样就能正确回显                           。这种思路其实本质上就是自己写lazyLoad的逻辑                         ,放弃使用官方提供的lazyLoad方法        。 2.将 el-cascader 组件 重新渲染一次                 ,既然首次加载的时候能正确调用lazyLoad     ,那每次都重新来                          ,都当成首次加载就好了                     ,这就是用v-if解决的思路            。

两种解决思路没有什么优劣之分,本质都是打补丁                           。希望element-ui官方能修复这个问题                      ,这样我们也不用折腾了            。

思路二解决起来更简单                         ,这里使用的也是思路二解决:

<el-cascader v-if="editCascaderVisible" v-model="IdList" :props="props" ></el-cascader>

然后在editRow方法时     ,手动控制它刷新一次:

editRow(rowData) { this.editCascaderVisible = false; // 这里搞个定时器重新载入一下组件就可以触发组件拉取数据 setTimeout(() => { this.editCascaderVisible = true; }, 1); this.IdList= []; //在编辑的时候等到DOM更新完成再赋值 this.$nextTick(() => { //将选中数据的值 赋值给表单 this.dataForm = Object.assign({}, rowData); }); //调用后端接口                  ,获取自顶向下逐个层级ID的列表 this.IdList= this.api_getIdList(rowData.groupId); //打开修改弹窗 this.dialogVisible = true; }

这样每次点击编辑的时候                        ,就都能正确回显了        。

三         、点击单选框选中节点不加载下一级选项

因为我们使用的是lazyLoad模式         ,点击单选框选中时              ,不会触发加载下一级选项                        ,如图:

解决办法:

<el-cascader @change="handleChange" v-if="editCascaderVisible" v-model="IdList" :props="props" ></el-cascader> //处理单选点击事件 handleChange(e) { this.$nextTick(() => { const dom = document.getElementsByClassName("el-radio is-checked"); //这里我把dom打出来看了 最后一个选项才是我选中的节点 即[length-1] 有的博主写的是 第一个元素 即[0] 大家自行尝试 let radioDom = dom[dom.length - 1]; const brother = radioDom.nextElementSibling; brother.click(); }); },

原理:我们点击标签即label             ,组件就会触发加载下一级节点          ,所以当选中的节点发生变化时                         ,我们手动触发点击它的同级下一个元素                 ,也就是label     ,达到加载下一级节点的目的                           。

四              、点击label标签直接选中

单选的情况下                          ,要选中需要点击radio按钮                     ,非常不方便,需要设置成点击标签页直接选中

<style> /*单选的级联选择器                      ,点击标签页就可以选中*/ .el-cascader-menu .el-radio { display: table; vertical-align: middle; width: 100%; height: 100%; position: absolute; box-sizing: border-box; margin-left: -25px; padding-left: 15px; margin-top: 6px; } .el-cascader-menu .el-radio .el-radio__input { display: table-cell; vertical-align: middle; } </style>

用css就可以解决                         ,原理是:把单选框的范围放大到整个标签范围     ,点击标签相当于点单选框                 。

附:

记录一下解决过程中对 el-cascader 组件的认识:

<el-cascader ref="editCascader" v-model="departmentIdList" :props="propsSearch" placeholder="请选择业务部门" style="width: 15vw" ></el-cascader>

加入ref                  ,可以使用

this.$refs.editCascader.panel

获取到 el-cascader 对象

可以使用

this.$refs.editCascader.panel.lazyLoad(cqbankNode);

 主动调用lazyLoad绑定的方法                        ,传入的节点要有chidren字段         ,或者直接取自

let cqbankNode = this.$refs.editCascader.panel.menus[0][0];

menus是菜单项

menus[0]即第一个下拉框列表              ,

menus[1]即第二个下拉框列表                        ,可以通过修改menus             ,修改下拉框展示列    。

但是根据 menus[0][0] 去获取          ,有时候节点children为空                         ,可能应该换一个属性去获取                 ,这个思路应该也能做     ,当时是取值属性来源错了                          ,为空就写不下去了就换思路了                          。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
计算机毕设做什么系统(【计算机毕业设计】在线考试系统) pytorch加载模型继续训练(Pytorch深度学习实战3-7:详解数据加载DataLoader与模型处理)