当前位置: 首页 > news >正文

elementui Cascader 级联选择器 每个一级节点下只能选择一个节点

在网上找到了一篇文章https://www.jb51.net/javascript/302754q75.htm (可以先看下这个文章,确实给出了很不错的思路)拿到右侧面板id值就能知道对应选项的id值,再触发li标签的孩子标签中的checkbox的点击事件就可以了。但是忽略了一个事情,就是三级的时候面板id都是一样的所以根据索引根本找不到对应的dom。只有二级的时候是有效的看下图对比

image

image

 都是同一个一级下面 面板id虽然不一样,但是之前的9279你通过代码获取到后 这个dom是没有了换成了新的8964所以开头那篇文章不能作为最终的解决方法。
最后我准备获取不到dom的时候就去修改值下面是代码

  <el-cascaderref="prouductSysRef":key="cascaderKey"v-model="formData.productSysteminfo":options="productOptions":props="productSystemProps"@change="handleProductChange"><template slot-scope="{ node, data }"><el-popoverplacement="top"trigger="hover":open-delay="1000"><div class="popover-content">{{ data.atlasName }}</div><div slot="reference" class="cascader-node-label">{{ data.atlasName }}</div></el-popover></template></el-cascader>
data(){
return {
cascaderKey:0,productOptions: [],productSystemProps: {value: 'atlasId',label: 'atlasName',children: 'children',lazy: false,multiple: true,checkStrictly: true,leaf: 'leaf'},
}
}// 同一父级下只选一个子级
    handleProductChange(value) {const selectedPaths = this.formData.productSysteminfo || [];// 单班型模式:只能选一个,选中新的取消之前的if (this.singleClassTypeInfo) {if (value && value.length > 1) {const prev = this.prevValue || [];const added = value.find(v => !prev.some(p => JSON.stringify(p) === JSON.stringify(v)));this.prevValue = value;if (added) {this.formData.productSysteminfo = [added];}} else {this.prevValue = [selectedPaths[selectedPaths.length - 1]];}return;}// 多班型模式:每个一级节点下只能选一个,选中新的通过 JS 点击取消同一一级下之前的// 如果是取消勾选触发的二次 change,直接更新 prevValue 并返回if (this.isCancellingItem) {this.isCancellingItem = false;this.prevValue = [...value.filter(p => p.length > 1)];return;}// 过滤掉一级节点的选中项if (!value || !value.length) {this.prevValue = [];return;}const validValue = value.filter(p => p.length > 1);const validPrev = (this.prevValue || []).filter(p => p.length > 1);// 按一级分组const groupByRoot = arr => {const groups = {};for (const path of arr) {const rootId = path[0];if (!groups[rootId]) groups[rootId] = [];groups[rootId].push(path);}return groups;};const currentGroups = groupByRoot(validValue);const prevGroups = groupByRoot(validPrev);console.log(currentGroups, 'cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc');console.log(prevGroups, 'pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp');// 遍历当前每个一级,找新增项和需要取消的项for (const rootId in currentGroups) {const currentPaths = currentGroups[rootId];const prevPaths = prevGroups[rootId] || [];// 找出新增的项const added = currentPaths.find(v => !prevPaths.some(p => this.isSamePath(p, v)));console.log(added, '111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111', prevPaths);if (added && prevPaths.length > 0) {// 有新增项,且之前该一级下有选中项,需要取消之前的const toCancel = prevPaths[0];// 通过 JS 点击取消勾选this.cancelCascaderItem(toCancel);// 只处理第一个有变化的,因为取消后会再次触发 changereturn;}}// 没有需要取消的,直接更新 prevValuethis.prevValue = [...validValue];},// 通过 JS 点击取消级联选择器中的勾选
    cancelCascaderItem(path) {this.$nextTick(() => {try {// 获取要取消的项的 atlasId(路径最后一项)const targetId = path[path.length - 1];// 直接通过 atlasId 查找对应的 DOM 元素const labelElement = document.getElementById(targetId);if (labelElement) {// 找到了,向上查找最近的 li,然后找 el-checkboxconst liElement = labelElement.closest('li');if (liElement) {const checkbox = liElement.querySelector('.el-checkbox');if (checkbox) {// 设置标志位,跳过取消勾选触发的二次 change 处理this.isCancellingItem = true;checkbox.click();return;}}}// 找不到 DOM 元素,直接修改值this.cancelByValue(path);} catch (e) {console.error('取消级联选择器勾选失败:', e);this.cancelByValue(path);}});},// 通过直接修改值来取消勾选(当 DOM 操作不可用时)
    cancelByValue(path) {const currentValue = this.formData.productSysteminfo || [];const newValue = currentValue.filter(p => !this.isSamePath(p, path));this.prevValue = [...newValue.filter(p => p.length > 1)];this.formData.productSysteminfo = newValue;// 强制级联选择器重新渲染// ++this.cascaderKey;
    },isSamePath(a, b) {return JSON.stringify(a) === JSON.stringify(b);}
代码层面确实可以准确的每级只选一个。但是还是有个致命bug,级联面板中右侧的部分(即子节点部分),会自动刷新跳转到第一个父级下的子级面板,就是赋值完自动刷新到第一个赋值的节点下面。
因为js取消checkbox就能避免这个问题,但是三级js就解决不了了。无解只能自己再手搓代码改变了。所以只用联级面板自己写
el-tag回显内容,可以尝试一下.

 

http://www.jsqmd.com/news/844185/

相关文章:

  • 从一次简单的登录绕过看起:HMS v1.0 SQL注入漏洞(CVE-2022-23366)的代码审计入门
  • 05_分支结构与多重选择_if和switch的使用
  • 【亲测免费】 网Conf客户端软件-Windows版:网络管理的得力助手
  • 告别传统绘图:Draw.io Mermaid插件让代码驱动图表生成变得简单
  • 告别轮询!STM32CubeMX配置DMA串口收发485数据,并详解HAL库回调函数使用避坑
  • 智能后视镜存储芯片选型:从eMMC到UFS的车规级实战指南
  • 智慧养老机器人体系:三层架构、场景落地与关键技术解析
  • CPPM证书的有效期与续证要求说明 - 众智商学院官方
  • Figma中文界面3分钟搞定:告别英文障碍的设计神器
  • CrewAI实战:多智能体协作开发完整指南
  • 沃尔玛购物卡回收服务,一键搞定! - 团团收购物卡回收
  • 百度季报图解:营收321亿 AI业务占比首次过半 DAA重塑AI价值标准
  • 大理石方尺批发赛道:紫青坤麟的合规交付与核心优势 - 奔跑123
  • 0503 光刻机 第五卷:EUV光源系统(S级 长期死磕突破)第3小节:产业化核心卡点(材料/工艺/软件/可靠性,全链路死磕)
  • HTTP 常用状态码速查表
  • 告别手动ping!用netspy这款神器,5分钟摸清内网所有存活网段
  • 手机号逆向查询QQ号:3分钟掌握Python自动化查询技巧
  • 告别本科论文 “写作内耗”:paperxie 智能写作,按部就班搞定毕业论文
  • obamify跨平台兼容性解决方案:从桌面到Web的完美迁移指南
  • 2026年,上海植物油燃料公司哪家可靠?这份推荐值得一看! - 速递信息
  • 2026 年 5 月东莞名表回收指南,收的顶全品牌可受理 - 奢侈品回收测评
  • 深耕深圳奢表回收:劳力士、欧米茄、百达翡丽回收行情与机构测评 - 奢侈品回收测评
  • 在AutoDL上租GPU服务器,用Keras/TensorFlow搞定Unet眼底血管分割(附完整代码)
  • Nacos AP 和 CP 模式
  • Key User Extensibility,SAP S/4HANA Cloud 里最容易被低估的一条扩展路径
  • 如何在5分钟内配置Zotero PDF翻译插件:新手快速入门终极指南
  • MySQL 面试题爆款详解:InnoDB 页机制、B+树索引、Buffer Pool、Redo Log、页分裂与性能优化一次讲透
  • 电力CPS离散事件仿真技术:DESTinE工具解析与应用
  • 微电网系统优质品牌盘点:国内头部厂商技术实力、定制能力与交付效率解析 - 品牌推荐大师
  • 长沙闲置黄金变现不踩坑!合扬免费鉴定,报价即实价,安心无忧 - 奢侈品回收测评