首页 > 其他分享 >Ant Design Vue Tree 选中子节点同时半选中父级节点

Ant Design Vue Tree 选中子节点同时半选中父级节点

时间:2024-03-28 20:56:44浏览次数:25  
标签:Vue menu menuList item 菜单 选中 result 节点

需要实现的效果:

  • 1、子菜单如果不是全部选中,一级菜单半选。
  • 2、子菜单全选,一级菜单选中。
  • 3、一级菜单选择,二级菜单全选。
  • 4、没有二级菜单,则只控制一级菜单。

主要用到的属性是checkedhalfCheckedKeys,通过手动控制那些菜单选中,那些半选中实现功能。

**页面截图: **

完整代码如下:

<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>

完成!

标签:Vue,menu,menuList,item,菜单,选中,result,节点
From: https://www.cnblogs.com/zhangans/p/18102548

相关文章

  • 基于vue.js的购物商场的设计与实现
     有需要的同学,源代码和配套文档领取,加文章最下方的名片哦一、项目演示项目演示视频https://graduation-images.oss-cn-beijing.aliyuncs.com/videos/828%E5%A5%97ssm%E5%BD%95%E5%83%8F/10773_ssm616%E5%9F%BA%E4%BA%8Evue.js%E7%9A%84%E8%B4%AD%E7%89%A9%E5%95%86%E5%9C%BA......
  • vue3 mitt事件总线,组件之间通信,通信范围不在局限于父子组件之间
    vue2使用的EventBus事件总线在vue3已经被弃用了;vue3使用的事件总线为mitt,可用父子组件,兄弟组件之间通信我使用的方法如下新建一个mitt.ts文件保存以下内容importmitts,{Emitter}from"mitt";//定义类型别名,因全局使用并且需要自定义事件名称,所以使用索引签名......
  • Vue学习笔记Day01
    软件安装:node.jsvscode一、基于脚手架创建前端工程(一)环境要求:1.node.js:前端项目的运行环境;(查看版本号:node-v)2.npm:JavaScript的包管理工具;(查看版本号:npm-v)3.VueCLI:基于Vue进行快速开发的完整系统,实现交互式的项目脚手架。(安装VueCLI:npmi@vue/cli-g)(二)使用Vue......
  • vue之实现单击与双击、同一标签使用click实现单双击操作、不选最后一个子元素的选择器
    MENUhtmlJavaScriptstyle解析html<template><divclass="box"><divclass="box_content"><pclass="box_p1"@click.prevent="tabSwitch({id:'keyId'})">......
  • vue extends继承后修改template的解决方案
    vueextends继承后怎么注入虚拟DOM节点1.需求使用extends继承一个组件并在上面做功能的修改和扩展,同时需要小小修改一部分的template。2.extend原理使用extends时,你实际上是创建了一个新组件,它包含了父组件的所有选项和数据,但是你可以覆盖或添加新的选项。3.问题修改通过ext......
  • Vue 自定义组件库通过配置调整样式?
      在Vue自定义组件库中,通常可以通过配置来调整样式。为了实现这一点,你可以定义一组样式相关的配置项,并在组件内部使用这些配置项来动态地设置样式。以下是一个简单的示例,演示了如何通过配置调整组件的样式。自定义组件(CustomComponent.vue)<template><div:style......
  • 11-Vue-生命周期
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>引出生命周期</title><scripttype="text/javascript"src="../js/vue.js"></script></head&......
  • ONLYOFFICE 文档 Vue 组件
    ONLYOFFICE文档Vue组件ONLYOFFICEDocsVue.js 组件 集成ONLYOFFICEDocs到 Vue.js 项目。先决条件此过程需要 Node.js(和npm)。使用ONLYOFFICE文档编辑器创建演示Vue.js应用程序此过程创建一个基本Vue.js应用程序 并在其中安装ONLYOFFICE文档编辑器。......
  • 若依RuoYi-Vue创建菜单并添加自定义页
    全文见:若依管理系统RuoYi-Vue(一):项目启动和菜单创建添加菜单和页面是若依管理系统最核心的功能,也是使用者最关心的事情,这里涉及到核心中的核心功能:权限,先不考虑那么多,直接新增页面,看看能否生效。下面演示新闻列表页添加的过程,这里如果想要新增新闻列表菜单,需要先新增“新闻”父菜......
  • KingbaseES 执行计划常见节点介绍
    KingbaseES中explain命令来查看执行计划时最常用的方式。其命令格式如下:explain[option]statement其中option为可选项,常用的是以下5种情况的组合:analyze:执行SQL并且显示实际的运行时间和其他统计信息,默认FALSE。注意:加了analyze会真正执行SQL语句verbose:显示附加信息,比如......