vue3.0+Ts+全局自定义指令实现动态按钮【操作】

本文介绍了如何使用Vue3.0结合TypeScript和全局自定义指令实现动态权限按钮的控制。首先,从后端获取动态路由并在Vuex中处理,将路由和按钮权限存储。然后,通过自定义指令`v-hasPermission`动态判断按钮是否显示,根据用户权限展示或隐藏操作按钮。整个流程包括路由处理、Vuex状态管理以及模板文件中的指令应用。
摘要由CSDN通过智能技术生成

1.介绍

        本文采用vue3.0+Ts+全局自定义指令实现动态按钮【操作】,应用场景为后端发送动态菜单+操作,操作信息存放在路由的meta中并将路由存在vuex中。模板文件使用全局自定义指令动态判断是否显示该按钮。

2.编写路由相关内容

2.1.先看下处理完后的路由meta中按钮的存放形式

2.2. 构建树,处理后端返回的路由

2.2.1 在auctions中调用函数获取后端路由(我这里是带有模块的,如果默认就是菜单无需考虑模块)

    generateRoutes( {commit}: ActionContext<userState, userState> ) {
        let modelId = store.getters.modelId;
        return new Promise(resolve => {
            getMenu({
                modelId: modelId
            }).then(response => {
                if (response.status === 20000) {
                    let data = tree(response.data, modelId)
                    commit('SET_ROUTES', response.data)
                    resolve(data)
                    return
                }
            })
        })
    },

后端返回数据如下 

{
	"status": 20000,
	"message": "获取菜单",
	"data": [
		{
			"id": 2,
			"path": "/main/systemManage",
			"icon": "fa fa-bar-chart-o",
			"name": "数据看板",
			"pid": 1,
			"type": 2,
			"affix": 0,
			"url": "",
			"redirect": "/main/systemManage/dashbord"
		},
		{
			"id": 3,
			"path": "/main/systemManage/dashbord",
			"icon": "fa fa-bar-chart-o",
			"name": "数据看板",
			"pid": 2,
			"type": 3,
			"affix": 0,
			"url": "/main/systemManage/dashboard/index",
			"redirect": ""
		},
		{
			"id": 4,
			"path": "/main/systemManage/auth",
			"icon": "sfont system-menu",
			"name": "权限管理",
			"pid": 1,
			"type": 2,
			"affix": 0,
			"url": "",
			"redirect": ""
		},
		{
			"id": 5,
			"path": "users",
			"icon": "",
			"name": "管理员列表",
			"pid": 4,
			"type": 3,
			"affix": 0,
			"url": "/main/systemManage/users/index",
			"redirect": ""
		},
		{
			"id": 20,
			"path": "",
			"icon": "",
			"name": "删除",
			"pid": 5,
			"type": 4,
			"affix": 0,
			"url": "delete",
			"redirect": ""
		},
		{
			"id": 6,
			"path": "role",
			"icon": "fa fa-life-bouy",
			"name": "权限组列表",
			"pid": 4,
			"type": 3,
			"affix": 0,
			"url": "/main/systemManage/role/index",
			"redirect": ""
		},
		{
			"id": 7,
			"path": "menu",
			"icon": "fa fa-sitemap",
			"name": "菜单管理",
			"pid": 4,
			"type": 3,
			"affix": 0,
			"url": "/main/systemManage/menu/index",
			"redirect": ""
		}
	]
}

2.2.2 前端在vuex中处理数据,附上操作菜单和按钮的tree,这里面type【2:目录,3:菜单,4:按钮操作】

export function tree( arr: Array<any>, pid: internal ) {
    const treeArr: Array<any> = []
    arr.forEach(( item ) => {
        if (item.pid == pid && item.type != 4) {
            item.meta = {
                title: item.name,
                icon: item.icon,
                affix: (item.affix === 1),
                noCache: true,
                btnPermissions: []
            }
            if (item.type === 2) {
                item.component = Layout
                if (!item.redirect) {
                    item.redirect = 'noRedirect'
                }
            } else if (item.type === 3) {
                item.component = routeAllPathToCompMap[`../../views${item.url}.vue`];
                item.meta.btnPermissions = getBtnPermissions(arr, item.id)
            }
            item.children = tree(arr, item.id)
            if (item.children.length <= 0) {
                item.children = []
            }
            treeArr.push(item)
        }
    })
    return treeArr
}

function getBtnPermissions( arr: Array<any>, pid: internal ) {
    let array: any = [];
    arr.forEach(( item: any ) => {
        if (item.type === 4 && item.pid === pid) {
            array.push(item.url)
        }
    })
    return array;
}

2.2.3. 在mutations中将路由存到vuex中

  SET_ROUTES( state: userState, routes: Array<any> ) {
        state.addRoutes = routes
    },

3. 当访问每一个路由的时候需要将这个路由的meta中的按钮权限存在vuex中,用于判断当前路由的操作权限

 setPermissions: ( state: userState, permissionsArr: Array<any> ) => {
        state.permissions = permissionsArr
    },

4.构建全局自定义指令

4.1. 在src的utils目录中(没有就创建一个)新建如下目录

 

4.2. 实现btnPermissions.ts

// 注册一个全局自定义指令 `v-hasPermission`
import store from "@/store";

export default function ( app: any ) {
    app.directive('hasPermission', {
        mounted( el: any, binding: any ) {
            const {value} = binding;
            const usersPermissions = store.getters.permissions;
            let f = usersPermissions.some((item:any) => {
                //some会循环所有元素,如果有一个元素满足则返回true并跳出循环,如果都没有则返回false
                return item.indexOf(value) !== -1;
            });
            if (!f) {
                ///如果不满足则通过dom元素销毁这个按钮
                el.parentNode && el.parentNode.removeChild(el);
            }
        }
    })
}

4.3. 实现index.ts

import hasPermission from "./btnPermissions"

export default function registerDirectives( app: any ) {
    hasPermission(app)
}

4.4. 全局挂载,main.js中引入刚刚的index.ts,并调用注册函数

5.模板文件中使用

        <el-button v-hasPermission="['create']" type="primary" :icon="Plus" @click="handleAdd">添加
        </el-button>

6.效果图

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凉臣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值