Vue2.0权限树组件实现代码

前端之家收集整理的这篇文章主要介绍了Vue2.0权限树组件实现代码前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

项目使用的饿了么的Element-Ui,权限树使用其树形控件:

刚开始没有特殊需求,三级分支,效果看着还可以。但是接下来的新需求:增加页面操作按钮权限,即达到四级分支,同时要求四级权限布局方式为横向,而且操作按钮权限非固定四级树,但是样式要求一致。这样子就很难操作了,如果单单是四级树为横向,还可以调调样式完成。本来想修改element的tree控件源码来实现,网上查了一些资料,还没有很好的办法生成其编译文件。最终决定自己写组件完成上述需求。

先上效果图:

基本可以满足需求,样式稍微比element差点,后期再优化。

组件代码如下:

  • Box" class="checkCls" @click.stop="selTree(model)" :id="'menu'+model.id" :class="'group'+label"> {{ model.menuName }}
  • <script type="text/ecmascript-6">
    import $ from 'jquery'
    export default {
    name: 'treeMenu',props: ['model','menuList','label','selectKeys'],data () {
    return {
    open: true,// 默认打开彩单树
    selAllkeys: []
    }
    },computed: {
    isFolder: function () {
    return this.model.childNode && this.model.childNode.length
    },isButton: function () {
    if (this.model.buttonControl === '1') {
    return 'btnCls'
    } else {
    return 'menuCls'
    }
    },hasBorder: function () {
    if (this.model.menuLevel === 1) {
    return 'blk_border'
    }
    }
    },methods: {
    getAllKeys () {
    var keys = []
    var objs = $('.group' + this.label + ':checked')
    for (let i = 0; i < objs.length; i++) {
    let id = objs[i].id
    id = id.substring(4)
    keys.push((id - 0)) // 保存选中菜单id
    }
    return keys
    },toggle: function () {
    if (this.isFolder) {
    this.open = !this.open
    }
    },// 根据id获取menu对象
    getMeunById (id,allMenuList) {
    var menu = {}
    if (allMenuList.id === id) { // 一级菜单
    menu = allMenuList
    } else if (allMenuList.childNode && allMenuList.childNode.length) { // 二级菜单
    for (let i = 0; i < allMenuList.childNode.length; i++) {
    if (allMenuList.childNode[i].id === id) {
    menu = allMenuList.childNode[i]
    break
    } else if (allMenuList.childNode[i].childNode && allMenuList.childNode[i].childNode.length) { // 三级
    for (let j = 0; j < allMenuList.childNode[i].childNode.length; j++) {
    if (allMenuList.childNode[i].childNode[j].id === id) {
    menu = allMenuList.childNode[i].childNode[j]
    break
    }
    }
    }
    }
    }
    return menu
    },// checkbox点击事件
    selTree (model) {
    var obj = $('#menu' + model.id)[0] // checkbox DOM对象
    if (obj.checked) { // 选中
    // 若存在下级,下级全部选中
    if (model.childNode && model.childNode.length) {
    this.subMenusOp(model.childNode,1)
    }
    // 若存在上级,确认是否需要选中上级CheckBox
    if (model.supMenuID !== 0 && model.menuLevel > 2) {
    this.supMenusOp(model.supMenuID,1)
    }
    } else { // 取消
    // 若存在下级,下级全部取消
    if (model.childNode && model.childNode.length) {
    this.subMenusOp(model.childNode,0)
    }
    // 若存在上级,确认是否需要取消上级CheckBox
    if (model.supMenuID !== 0 && model.menuLevel > 2) {
    this.supMenusOp(model.supMenuID,0)
    }
    }
    this.getAllKeys()
    },// 下级菜单操作 flag=1为选中,flag=0为取消
    subMenusOp (childNodes,flag) {
    for (let i = 0; i < childNodes.length; i++) {
    var menu = childNodes[i]
    var id = menu.id
    if (flag === 1) { // 选中
    $('#menu' + id)[0].checked = true
    } else { // 取消
    $('#menu' + id)[0].checked = false
    }
    if (menu.childNode && menu.childNode.length) {
    this.subMenusOp(menu.childNode,flag)
    }
    }
    },// 上级菜单操作(选中:flag=1,取消:flag=0)
    supMenusOp (id,flag) {
    var menu = this.getMeunById(id,this.menuList)
    if (menu.childNode && menu.childNode.length) {
    var childLength = menu.childNode.length // 直接子级个数
    var selectCount = 0
    for (let i = 0; i < childLength; i++) {
    let id1 = menu.childNode[i].id
    if ($('#menu' + id1)[0].checked) {
    selectCount++
    }
    }
    if (flag === 1) { // 选中
    if (childLength === selectCount) {
    $('#menu' + id)[0].checked = true
    if (menu.supMenuID !== 0 && menu.menuLevel > 2) {
    this.supMenusOp(menu.supMenuID,flag)
    }
    }
    } else if (flag === 0) {
    if (childLength !== selectCount) {
    $('#menu' + id)[0].checked = false
    if (menu.supMenuID !== 0 && menu.menuLevel > 2) {
    this.supMenusOp(menu.supMenuID,flag)
    }
    }
    }
    }
    },// 计算所有下级节点是否全部选中,是返回true,否返回false
    isAllSel (childNodes,selectKeys) {
    var nodeKeys = [] // 选中的id集合
    this.addKeys(childNodes,selectKeys,nodeKeys)
    var allKeys = []
    this.getNodesCount(childNodes,allKeys)
    if (nodeKeys.length === allKeys.length) {
    return true
    } else {
    return false
    }
    },// 计算childNodes下选中的id集合
    addKeys (childNodes,Arrs) {
    for (let i = 0; i < childNodes.length; i++) {
    if (selectKeys.indexOf(childNodes[i].id) >= 0) {
    Arrs.push(childNodes[i].id)
    }
    if (childNodes[i].childNode && childNodes[i].childNode.length) {
    this.addKeys(childNodes[i].childNode,Arrs)
    }
    }
    },// 计算childNodes的子级数
    getNodesCount (childNodes,allKeys) {
    for (let i = 0; i < childNodes.length; i++) {
    allKeys.push(childNodes[i].id)
    if (childNodes[i].childNode && childNodes[i].childNode.length) {
    this.getNodesCount(childNodes[i].childNode,allKeys)
    }
    }
    }
    },mounted () {
    // 禁止复选框的冒泡事件
    $("input[type='checkbox']").click(function (e) {
    e.stopPropagation()
    })
    // 选中菜单使能
    if (this.selectKeys instanceof Array && this.selectKeys.length > 0 && this.selectKeys.indexOf(this.model.id) >= 0) {
    if (this.model.childNode && this.model.childNode.length && this.model.menuLevel !== 1) { // 包含子级,一级菜单除外
    // 计算所有子节点是否全部选中
    if (this.isAllSel(this.model.childNode,this.selectKeys)) {
    $('#menu' + this.model.id)[0].checked = true
    }
    } else {
    $('#menu' + this.model.id)[0].checked = true
    }
    }
    }
    }

    权限树的数据结构有一定要求,比element的tree控件数据结构属性稍多一些,否则实现也不会这么简单了,优化后的权限树数据结构在选中菜单返回上简化了很多,也没有用到vuex。

    权限树数据结构为:

    {
    'childNode': [
    {
    'childNode': [
    {
    'icon': '','id': 242,'menuLevel': 3,'menuName': '旅游订单','menuTop': 1,'menuUrl': '/','buttonControl': '0','supMenuID': 241
    },{
    'icon': '','id': 243,'menuName': '签证订单','menuTop': 2,'id': 244,'menuName': '出团通知书','menuTop': 3,'supMenuID': 241
    }
    ],'icon': '','id': 241,'menuLevel': 2,'menuName': '订单管理','supMenuID': 240
    },{
    'childNode': [
    {
    'icon': '','id': 246,'menuName': '旅游产品','menuUrl': '/tourProduct','supMenuID': 245
    },'id': 247,'menuName': '图库','menuUrl': '/basePicStore','id': 248,'menuName': '签证产品','supMenuID': 245
    }
    ],'id': 245,'menuName': '产品管理','id': 250,'menuName': '旅游广告','supMenuID': 249
    }
    ],'id': 249,'menuName': '广告管理','supMenuID': 240
    }
    ],'id': 240,'menuLevel': 1,'menuName': '业务中心','supMenuID': 0
    }

    实际数据为上述对象的数组。

    这里主要增加buttonControlsupMenuId,方便实现按钮权限的样式判断和选中、取消操作的checkBox级联操作。

    引用组件代码

    theModel即为权限树数组,selectKeys为选中的权限数组集合,即id集合。

    mounted()实现初始化操作:禁止checkBox的冒泡时间,selectKeys的赋值操作。

    其实权限树或者说菜单树的要点就在递归算法上,按钮的选中或取消,都需要执行递归操作。这里使用jQuery来协助操作,简化了许多事情,应该还是数据绑定的精神没有掌握好吧。getAllKeys()获取checkBox为true的权限id返回。 实际获取选中的权限菜单的数据如下图:

    总结

    以上所述是小编给大家介绍的Vue2.0权限树组件实现代码。编程之家 jb51.cc 收集整理的教程希望能对你有所帮助,如果觉得编程之家不错,可分享给好友!感谢支持

    原文链接:https://www.f2er.com/vue/36772.html

    猜你在找的Vue相关文章