- A+
所属分类:Web前端
需要实现的效果:
- 1、子菜单如果不是全部选中,一级菜单半选。
- 2、子菜单全选,一级菜单选中。
- 3、一级菜单选择,二级菜单全选。
- 4、没有二级菜单,则只控制一级菜单。
主要用到的属性是checked和halfCheckedKeys,通过手动控制那些菜单选中,那些半选中实现功能。
**页面截图: **
完整代码如下:
<template> <div> <a-tree v-model="checkedKeys" checkable :tree-data="menuList" @check="onCheck"></a-tree> </div> </template> <script> import { getRoleMenusById } from '@/api/role' import { getMenusList } from '@/api/menu' import { sortBykey, toTree } from '@/utils/common' export default { name: 'EditModal', data () { return { checkedKeys: [], record: {}, // 全部菜单 menuList: [], // 授权菜单 menuRole: [] } }, created () {}, mounted () {}, methods: { sortBykey, toTree, /** * 获取用户的授权菜单 * @param {*} menuId * @returns */ getUserMenus (menuId) { return new Promise((resolve, reject) => { getRoleMenusById(menuId).then((res) => { resolve(res) }).catch((err) => { reject(err) }) }) }, /** * 获取菜单列表 */ getMenusList () { return new Promise((resolve, reject) => { getMenusList().then((response) => { response = response.items response.forEach((item) => { item.title = item.name item.key = item.id }) response = this.sortBykey(response, 'sort') response = this.toTree(response) resolve(response) }).catch((err) => { reject(err) }) }) }, /** * 选中树状菜单 * @param {*} checkedKeys * @param {*} info */ onCheck (checkedKeys, info) { console.log(checkedKeys, info) this.checkedKeys = this.getCheckedKeys(this.menuList, checkedKeys) }, /** * 筛选选中,以及半选中 * 判断当前的节点是否选择,如果选中,判断主节点是否需要选中, 如果没选中,判断主节点是否要选中 * @param {*} menuList * @param {*} checkedMenu */ getCheckedKeys (menuList, checkedMenu) { console.log('checkedMenu', checkedMenu) console.log('menuList', menuList) const result = { checked: [], halfCheckedKeys: [] } // 选出二级菜单,那些选中 menuList.forEach((item) => { if (item.children) { const subAllMenu = item.children.map(item => item.key) const isCheckedAll = this.selectedAllSubMenu(subAllMenu, checkedMenu) if (isCheckedAll) { // 一级菜单全选 result.checked.push(item.key) // 二级菜单全选 result.checked = [...result.checked, ...subAllMenu] } else { // 二级菜单只选选中的 const subMenu = this.getSubMenu(item.children, checkedMenu) result.checked = [...result.checked, ...subMenu] if (subMenu.length) { // 根据二级菜单是否选中来半选一级菜单 result.halfCheckedKeys.push(item.key) } } } else { // 一级菜单选中是否选中 if (checkedMenu.indexOf(item.key) !== -1) { result.checked.push(item.key) } } }) return result }, /** * 检测子菜单是否都选中 * @param {*} sub * @param {*} menu */ selectedAllSubMenu (sub, menu) { for (const item of sub) { if (!menu.includes(item)) { // 如果sub中的某个元素不在superset中,则返回false return false } } // 如果所有元素都在menu中,则返回true return true }, /** * 获取选中的子菜单 * @param {*} sub * @param {*} menu */ getSubMenu (sub, menu) { const result = [] sub.forEach(item => { if (menu.indexOf(item.key) !== -1) { result.push(item.key) } }) return result }, /** * 初始化 * @param {*} record */ async init (record) { this.record = { ...record } this.$nextTick(async () => { // 全部菜单 this.menuList = await this.getMenusList() console.log('menuList', this.menuList) // 授权菜单 this.menuRole = await this.getUserMenus(this.record.menu_id) console.log('menuRole', this.menuRole) // 授权菜单特殊处理,子菜单未完全选中,父菜单半选中 // this.menuRole.menu 数据为 [2,6,7,8,9,10,11,12,13,16,17,18,19,20,21,22,24] this.checkedKeys = this.getCheckedKeys(this.menuList, this.menuRole.menu.split(',').map(Number)) }) } } } </script>
完成!