Vue.js实现父子级复选框联动选中逻辑的方法
Vue 父子复选框联动实现方案
实现逻辑
你需要实现的联动规则可以通过两个监听方法完成,核心逻辑围绕选中ID集合selectedMenu的增删操作:
- 父级选中时,批量添加所有子级ID到选中集合;父级取消时,批量移除所有子级和自身ID
- 子级操作时,统计当前父级下所有子级的选中状态:有任意子级选中就保留父级ID,全不选就移除父级ID
完整代码示例
首先是template部分,你原有的代码基本不用改,补充了可选的半选状态展示,符合常规交互习惯:
<div class="menu-padding padding-top" v-for="(data, index) in getAllMenu" :key="index" > <input type="checkbox" v-model="selectedMenu" :value="data.id" @change="select(data)" :indeterminate="isIndeterminate(data)" /> <label>{{ data.menu_name }}</label> <div class="padding-left" v-if="data.child.length > 0" > <div v-for="(data_child, childIndex) in data.child" :key="childIndex" > <input type="checkbox" v-model="selectedMenu" :value="data_child.id" @change="selectChild(data)" /> <label>{{ data_child.menu_name }} {{ data_child.id }}</label> </div> </div> </div>
然后是script部分的逻辑(Vue2/Vue3选项式API通用):
export default { data() { return { // 你的菜单原始数据 getAllMenu: [ { "id": 266, "parent_id": 0, "menu_name": "Server && DB Info", "menu_url": "#", "menu_icon": "fa fa-database", "order_by": 6, "has_child": 1, "child": [ { "id": 269, "parent_id": 266, "menu_name": "Client", "menu_url": "/server_and_db_info/client", "menu_icon": null, "order_by": 7, "has_child": 0, "child": [] }, { "id": 268, "parent_id": 266, "menu_name": "VPN", "menu_url": "/server_and_db_info/vpn", "menu_icon": null, "order_by": 8, "has_child": 0, "child": [] }, { "id": 262, "parent_id": 266, "menu_name": "Server", "menu_url": "/server_and_db_info/server", "menu_icon": "", "order_by": 9, "has_child": 0, "child": [] }, { "id": 267, "parent_id": 266, "menu_name": "Database", "menu_url": "/server_and_db_info/database", "menu_icon": null, "order_by": 10, "has_child": 0, "child": [] }, { "id": 271, "parent_id": 266, "menu_name": "Domain", "menu_url": "/server_and_db_info/domain", "menu_icon": null, "order_by": 15, "has_child": 0, "child": [] } ] } ], // 存储选中的菜单ID集合 selectedMenu: [] } }, methods: { // 父级复选框change事件 select(parentData) { const parentId = parentData.id const childIds = parentData.child.map(item => item.id) // 判断父级是否被选中 const isParentChecked = this.selectedMenu.includes(parentId) if (isParentChecked) { // 父级选中:添加所有子级ID,自动去重 this.selectedMenu = [...new Set([...this.selectedMenu, ...childIds])] } else { // 父级取消:移除父级和所有子级ID this.selectedMenu = this.selectedMenu.filter(id => id !== parentId && !childIds.includes(id)) } }, // 子级复选框change事件 selectChild(parentData) { const parentId = parentData.id const childIds = parentData.child.map(item => item.id) // 统计当前父级下已选中的子级数量 const checkedChildCount = childIds.filter(id => this.selectedMenu.includes(id)).length if (checkedChildCount > 0) { // 有子级选中:如果父级未选中则添加 if (!this.selectedMenu.includes(parentId)) { this.selectedMenu.push(parentId) } } else { // 无子级选中:移除父级ID this.selectedMenu = this.selectedMenu.filter(id => id !== parentId) } }, // 可选:判断父级是否处于半选状态 isIndeterminate(parentData) { const childIds = parentData.child.map(item => item.id) const checkedChildCount = childIds.filter(id => this.selectedMenu.includes(id)).length return checkedChildCount > 0 && checkedChildCount < childIds.length } } }
注意事项
- 所有操作都基于数组
selectedMenu的增删,v-model会自动同步复选框的选中状态 - 半选状态不需要可以直接删除
indeterminate相关的属性和方法,不影响核心联动逻辑 - 代码支持多组父子菜单同时生效,只要
getAllMenu里存在多个父级节点,逻辑会自动适配
内容的提问来源于stack exchange,提问作者alprazolam
相关产品推荐
相关产品推荐

