el-cascader 实现最后一级点击一行选中,无需点击单选框!!
我是将el-cascader 封装成组件了
父亲 这样引用
<el-form-item label="作业申请单位" prop="name"> <TaskUnit :value.sync="queryParams.name" placeholder="请选择"></TaskUnit> </el-form-item>
废话不多说直接上组件代码!!!!
要实现对最后一级(叶子节点)点击文字也可以选定的功能,我们需要修改组件逻辑和样式。这通常需要通过自定义 el-cascader
的展示节点,并为最后一级添加特殊的点击事件处理。
下面是代码:
<template> <el-cascader ref="cascader" @change="changeUnit" :title="title" v-model="taskUnit" :options="taskUnitOption" :props="propsData" :show-all-levels="false" clearable :placeholder="placeholder" > <!-- 自定义节点内容,使最后一级点击文字可选 --> <template slot-scope="{ node, data }"> <span class="custom-node-content" :class="{ 'leaf-node': isLeafNode(data) }" @click="handleNodeClick(node, data, $event)" > {{ node.label }} </span> </template> </el-cascader> </template> <script> import { getList} from "@/api/system/user"; /** * @description * 作业单位的级联选择器 * @property {String} value 绑定值 .sync修饰 * @property {String} valueName 绑定值中文 .sync修饰 * @property {String} placeholder 组件占位符 */ export default { name: 'TaskUnit', props: { value: { type: String, default: '' }, valueName: { type: String, default: '' }, placeholder: { type: String, default: '' } }, data() { return { //列表 taskUnitOption: [], // 作业单位绑定值 taskUnit: [], // 显示的title title: '', // Cascader 组件的属性配置 propsData: { checkStrictly: true, value: 'id', // label: 'name', // 假设你的选项中有 name 字段用于展示 // children: 'children', // 假设选项中有 children 字段用于子节点 expandTrigger: 'hover' // 悬停时展开子菜单 } }; }, watch: { // 监听外部value变化,同步到内部taskUnit value: { handler(val) { if (val) { this.taskUnit = val.split(','); this.updateTitle(); // 更新标题 } else { this.taskUnit = []; // 没传值时赋值为空 this.title = ''; // 清空标题 } }, immediate: true // 立即执行,确保组件加载时同步 } }, mounted() { this.init(); // 初始化 }, methods: { // 选择单位 changeUnit(list) { console.log('选择列表:', list); const nodes = this.$refs.cascader.getCheckedNodes(); if (nodes.length === 0) { this.title = ''; // 清空标题 this.$emit('update:value', ''); this.$emit('update:value-name', ''); return; } // 更新标题 this.updateTitle(nodes[0]); // 绑定数据 this.$emit('update:value', list.join(',')); this.$emit('update:value-name', this.title); }, // 更新标题 updateTitle(node) { if (!node) return; const labelList = node.pathLabels || []; this.title = labelList.join('/'); }, // 列表 async getTaskUnit() { try { const res = await getList(); // 改为不根据用户权限进行控制 this.taskUnitOption = res.data || []; // 确保防止 undefined } catch (error) { console.error('获取作业单位列表失败:', error); this.$message.error('获取作业单位列表失败'); } }, // 初始化函数 init() { this.getTaskUnit(); // 获取单位列表 }, /** * 判断节点是否为叶子节点 * @param {Object} data - 节点数据 * @returns {Boolean} 是否为叶子节点 */ isLeafNode(data) { return !data.children || data.children.length === 0; }, /** * 处理节点点击事件 * @param {Object} node - 级联选择器节点对象 * @param {Object} data - 节点数据 * @param {Event} event - 点击事件对象 */ handleNodeClick(node, data, event) { // 只有在点击叶子节点文本时才触发选中 if (this.isLeafNode(data)) { event.stopPropagation(); // 阻止冒泡,防止触发其他点击事件 // 构建选中路径 const path = []; let currentNode = node; while (currentNode) { path.unshift(currentNode.value); currentNode = currentNode.parent; } // 直接设置选中值 this.taskUnit = path; // 触发选中事件(模拟change事件) this.$nextTick(() => { this.changeUnit(path); // 手动关闭下拉菜单 if (this.$refs.cascader && typeof this.$refs.cascader.toggleDropDownVisible === 'function') { this.$refs.cascader.toggleDropDownVisible(false); } }); } } } }; </script> <style lang="scss" scoped> ::v-deep .el-input__suffix { display: none; } .el-cascader-menu__item { cursor: pointer; /* 鼠标指针变为手形,表示可点击 */ } /* 自定义样式:取消单选框的显示 */ .el-cascader-menu__item .el-checkbox { display: none; } /* 自定义节点内容样式 */ .custom-node-content { display: block; width: 100%; height: 100%; } /* 叶子节点的特殊样式 */ .leaf-node { cursor: pointer; color: #606266; transition: color 0.3s; &:hover { color: #409EFF; } } /* 确保整个节点区域可点击 */ ::v-deep .el-cascader-node__label { width: 100%; padding-right: 0; } /* 选中的样式 */ ::v-deep .el-cascader-menu__item.is-active { color: #409EFF; font-weight: bold; } </style>
实现说明
-
自定义节点内容:
- 使用
slot-scope
自定义节点的内容展示。 - 为每个节点添加了
custom-node-content
类,为叶子节点添加了leaf-node
类用于特殊样式。
- 使用
-
增加点击事件处理:
- 添加了
handleNodeClick
方法,专门处理节点点击事件。 - 在点击叶子节点文本时,会构建完整路径并触发选中效果。
- 使用
event.stopPropagation()
防止事件冒泡导致其他不需要的行为。
- 添加了
-
判断叶子节点:
- 添加
isLeafNode
方法,用于判断节点是否为叶子节点(没有子节点)。
- 添加
-
CSS 样式优化:
- 为叶子节点添加了特殊的悬停效果,使其看起来可点击。
- 确保节点的整个区域都可以点击,而不只是复选框。
-
手动关闭下拉菜单:
- 在点击叶子节点后,手动关闭级联选择器的下拉菜单,提供更好的用户体验。
这个实现确保了在保留原有功能的基础上,当用户点击最后一级(叶子节点)的文本时,也能够正确选中该节点。样式上也进行了适当的调整,使叶子节点的可点击性更加明显。