vue权限按钮的实现

这篇具有很好参考价值的文章主要介绍了vue权限按钮的实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

鉴权函数

由于下面几种方式都需要用到鉴权函数,所以将其放置在组件外面,供组件或其他文件调用。

// src/utils/hasPermission.js

import { usePermissionStore } from '@/stores'
import array from 'lodash/array'
export const hasPermission = (value, def = true) => {
  // 不传值,默认视为有权限,不做鉴权
  if (!value) {
    return def
  }

  const allCodeList = usePermissionStore().getPermCodeList
  // 如果不是数组,直接判断pinia里的权限数组有没有相同的元素即可
  if (!Array.isArray(value)) {
    return allCodeList.includes(value)
  }
  // intersection是lodash提供的一个方法,用于返回一个所有给定数组都存在的元素组成的数组
  return array.intersection(value, allCodeList).length > 0
}

将可以操作按钮的权限码们以权限码数组的形式存放到了pinia中,所以要先获取pinia中的权限数组再进行判断。

  1. 情况一:没有传值,则无法做权限码的比对,所以可以认为不需要鉴权,返回true即可。
  2. 情况二:传入的值是权限码数值,不是数组,那么可以拿pinia中的权限码数组来检测是否包含该权限码,如果有则认为有权限返回true;否则返回false。
  3. 情况三:传入的值是权限码数组,此时需要拿传入的数组和pinia中的权限码数组进行比较,看看是否存在交集,如果有交集则说明有权限,返回true;否则返回false。

Pinia:

// store/index.js

import { createPinia } from "pinia";

const pinia=createPinia()

export default pinia

export  * from './modules/permission.js'
// store/modules/permission.js

import { defineStore } from 'pinia'
import { getPermissionList } from '@/api/permission'
export const usePermissionStore = defineStore('permission', {
  state: () => ({
    // 权限代码列表
    permCodeList: [101, 102, 778, 779]
  }),
  getters: {
    // 获取
    getPermCodeList() {
      return this.permCodeList
    }
  },
  actions: {
    // 存储
    setPermCodeList(codeList) {
      this.permCodeList = codeList
    },

    // 请求权限码
    async getPermissionCode() {
      const codeList = await getPermissionList()
      this.setPermCodeList(codeList)
    }
  }
})

方式一:v-if搭配鉴权函数实现权限按钮

引入鉴权函数,将该能够操作该按钮的权限码以实参形式传入鉴权函数,v-if根据返回值决定是否加载该按钮结构。

<template>
  <div>
    <button class="fun-btn" v-if="hasPermission([101])">你能看到我?-v-if函数实现</button>
  </div>
</template>

<script setup>
import { hasPermission } from '@/utils/hasPermission'
</script>

<style scoped lang="scss"></style>

方式二:组件+插槽 实现权限按钮

将按钮以插槽形式放入组件中,给组件以props传递权限码数据,组件中使用鉴权函数来判断传入的权限码是否符合条件,符合则渲染插槽中的结构(按钮),否则不渲染。

<!--components/PermisBtnComp.vue-->
<template></template>

<script>
// h函数  https://cn.vuejs.org/api/render-function.html#h
// defineComponent-函数签名 https://cn.vuejs.org/api/general.html#definecomponent
import { hasPermission } from '@/utils/hasPermission'
import { renderSlot, h, defineComponent } from 'vue'

export default defineComponent({
  props: {
    value: {
      type: [Number, String, Array],
      default: ''
    }
  },
  setup(props, { slots }) {
    return () => {
      // 根据权限判断结果来确定是否要渲染默认插槽的结构
      // 在 Vue 3 中,通过 renderSlot(父组件传入的插槽内容,插槽名) 函数进行插槽渲染时,需要将其导入并包含在组件的 setup 方法中。
      // 父组件引用子组件时,子组件标签内的默认内容对应的是:renderSlot(slots, 'default')
      // return hasPermission(props.value) ? h('div', renderSlot(slots, 'default')) : null

      // 免去renderSlot https://cn.vuejs.org/guide/extras/render-function.html#rendering-slots
      return hasPermission(props.value) ? h('div', slots.default()) : null
    }
  }
})
</script>

<style scoped lang="scss"></style>

方式三:自定义指令 实现权限按钮

自定义指令其实和第一种很像,就是我们自己出一个"v-if",只不过是专门用来做权限判断的指令。指令传入的数据即为权限码,指令内部根据指令绑定的数据来做鉴权判断。

注意点1:这里的mounted可能较容易实现,但需要注意updated的设计,考虑到有动态修改指令后面的权限码的可能,所以当涉及到指令后面的权限码修改后,要重新做鉴权判断。

注意点2:自定义指令在内部的鉴权判断后,如果不符合条件要移除指令所在的结构;如果符合条件的话,要把之前因为不符合条件被移除的结构要添加回来,也就是回添操作;回添操作为了避免不知道把原来的结构添加回来到哪个位置,这里使用了document.createComment() 即注释先做占位,等需要回添时使用replaceChild() 把注释替换为按钮结构。如果使用的是remove()removeChild()可能再放回来就不知道放到哪个位置了。

// src/directs/judge-permission.js

import { hasPermission } from '@/utils/hasPermission'

// removeDom、addDom的存在是为了保证自定义指令绑定的权限码数据变化后可以不刷新页面动态添加/移除自定义指令所在的dom节点
// 移除dom节点
const removeDom = (el) => {
  // 把注释点绑在元素上,方便后面使用
  el._placeholderNode = document.createComment('permission-btn')
  // 和父节点关联上,方便后面使用
  el._parentNode = el.parentNode
  // 父节点做子元素替换
  el.parentNode.replaceChild(el._placeholderNode, el)
}

// 把移除的dom节点添加回来
const addDom = (el) => {
  el._parentNode?.replaceChild(el, el._placeholderNode)
}

const mounted = (el, binding) => {
  const permisList = binding.value
  if (!permisList) return
  if (!hasPermission(permisList)) {
    // 移除当前dom节点
    // el.parentNode?.removeChild(el) // 通过父节点删除子自己
    // el.remove() // 自杀
    /* 
        权限值会变,那就涉及到更新后要不要将移除的dom节点添加回来
        为了能够知道添加回来的dom节点放到哪个地方,可以创建注释节点来占位
        在添加时只对那个位置的子元素做替换操作即可
    */
    removeDom(el)
  }
}

const updated = (el, binding) => {
  // 比对前后变化的值,相同不需要后续操作
  let valDiff = binding.value === binding.oldValue
  if (valDiff) return
  // 重新判断改值前后的权限变化,相同不需要后续操作(如:修改前就没权限,修改后依旧没权限,无需操作)
  let oldPermisStatus = hasPermission(binding.oldValue)
  let nowPermisStatus = hasPermission(binding.value)

  if (oldPermisStatus == nowPermisStatus) return
  if (nowPermisStatus) {
    addDom(el)
  } else {
    removeDom(el)
  }
}

export const permisDirect = {
  mounted,
  updated
}

main.js中添加指令:

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import pinia from './stores'
import {permisDirect} from '@/directs/judge-permission'

const app=createApp(App)
app.use(pinia)
app.directive('permis',permisDirect)
app.mount('#app')

根组件效果展示

<script setup>
import PermisBtnFun from './components/PermisBtnFun.vue'
import PermisBtnComp from './components/PermisBtnComp.vue'
import { ref } from 'vue'

const permis = ref(102)
const permisToggle = () => {
  // 由于@/utils/hasPermission中有判断!value则返回true,表示没传值默认不需要鉴权,返回true放行
  // 所以这里在调整权限值的时候不能改成0,因为!0==true,如果变化前就有权限(true),变化后想没权限改为0,刚好!0是true,弄巧成拙,依旧显示。
  permis.value === 102 ? (permis.value = 100) : (permis.value = 102)
}
</script>

<template>
  <div class="btns-container">
    <!-- v-if搭配函数方式 -->
    <PermisBtnFun />
    <!-- 组件+插槽方式 -->
    <PermisBtnComp :value="101">
      <button class="comp-slot-btn">就你能耐?-组件插槽实现</button>
    </PermisBtnComp>
    <!-- 自定义指令方式 -->
    <button class="vpermis-btn" v-permis="permis">你依旧能看得到我?-自定义指令实现</button>
    <!-- 修改自定义指令绑定的权限值,测试自定义指令updated中的移除和回添的操作 -->
    <button @click="permisToggle">修改自定义指令绑定的权限值</button>
  </div>
</template>

<style scoped>
.btns-container {
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  height: 400px;
}
/* ::v-deep usage as a combinator has been deprecated. Use :deep(<inner-selector>) instead. */
:deep(.fun-btn) {
  background-color: #acd384;
  color: #fff;
}
.vpermis-btn {
  background-color: #f38585;
  color: #fff;
}
.comp-slot-btn {
  background-color: #5aa3f8;
  color: #fff;
}
</style>

vue权限按钮的实现,Vue,vue.js,javascript,前端,pinia文章来源地址https://www.toymoban.com/news/detail-614197.html

到了这里,关于vue权限按钮的实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vue自定义指令实现按钮级的权限控制

    提示:原文参考链接*且听风吟 提示:钩子函数: 自定义指令有五个生命周期(也叫钩子函数),分别是: bind,inserted,update,componentUpdated,unbind 。 bind :只调用一次,指令第一次绑定到元素时调用。用这个钩子函数可以定义一个绑定时执行一次的初始化设置。( bind 时父节点

    2024年02月10日
    浏览(48)
  • 【VUE学习】权限管理系统前端vue实现3-登陆页面

             path: \\\'/login\\\' :指定了路由的路径为 \\\"/login\\\",表示该路由匹配到的 URL 是 \\\"/login\\\"。 name: \\\'login\\\' :指定了路由的名称为 \\\"login\\\",可以在代码中通过名称来进行路由导航。 component: () = import(\\\'../views/Login.vue\\\') :指定了该路由对应的组件为一个异步加载的组件。 使用箭头函

    2024年02月13日
    浏览(44)
  • Vue | Vue.js 全家桶 Pinia状态管理

    🖥️ Vue .js专栏:Node.js Vue.js 全家桶 Pinia状态管理 🧑‍💼 个人简介:一个不甘平庸的平凡人🍬 ✨ 个人主页:CoderHing的个人主页 🍀 格言: ☀️ 路漫漫其修远兮,吾将上下而求索☀️ 👉 你的一键三连是我更新的最大动力❤️ 目录 一、Pinia和Vuex的对比 什么是Pinia呢? Pina和

    2024年01月16日
    浏览(53)
  • vue3项目引入本地js文件,实现一个音频播放按钮

    目前有一个需求就是在网页上放置一个音乐控制按钮,并且是在vue3项目里面。于是小白的我遇到了2个问题,第一个问题是如何实现没有进度条的播放按钮,这个网上有现成的代码,可以通过js代码切换不同的图片或者是别的样式,并不算难;第二个问题是如何在vue3项目中引

    2024年02月19日
    浏览(57)
  • 【VUE学习】权限管理系统前端vue实现4-自定义icon实现

    template 部分:定义了组件的模板内容。在这里,使用了 svg 标签来创建一个 SVG 图标元素,并添加了一个 use 元素来引用具体的图标。 :xlink:href 属性使用了绑定语法,将 iconName 绑定为 use 元素的 xlink:href 属性的值。 script setup 部分:使用了 Vue 3 的 script setup 语法,用于编写组件

    2024年02月13日
    浏览(45)
  • [VUE学习]权限管理系统前端vue实现8-右上角用户头像显示实现

               next(‘/logon’) 、 next(to) 或者 next({ …to, replace: true })           在路由守卫中, 只有next()是放行 ,其他的诸如:next(‘/logon’) 、 next(to) 或者 next({ …to, replace: true })都不是放行, 而是:中断当前导航,执行新的导航                 他不是直接放行 二十

    2024年02月13日
    浏览(51)
  • vue权限管理——按钮控制

    根据right中的数据对应增删改查按钮  initDynamicRoutes给用户对应的router中动态添加meta元数据后,permission.js中通过router.currentRoute就可以获取 directives/permission.js 获取路由元数据中的rights权限和按钮上的action记录权限做比较:如果包含则有该权限,否则无权限,进行删除元素或者

    2024年02月11日
    浏览(45)
  • vue前端实现图片下载,实现点击按钮弹出本地窗口,选择自定义保存路径

    直接上代码,废话不多说,点关注,不迷路 一、下载代码 二、别找代码了,不用代码就可以实现 以下按照步骤一步一步来 按照红色箭头所指,用鼠标戳它 恭喜你,功能完成了

    2024年02月13日
    浏览(59)
  • 【前端Vue】Vue3+Pinia小兔鲜电商项目第2篇:什么是pinia,1. 创建空Vue项目【附代码文档】

    Pinia 是 Vue 的专属状态管理库,可以实现跨组件或页面共享状态,是 vuex 状态管理工具的替代品,和 Vuex相比,具备以下优势 提供更加简单的API (去掉了 mutation ) 提供符合组合式API风格的API (和 Vue3 新语法统一) 去掉了modules的概念,每一个store都是一个独立的模块 搭配

    2024年03月21日
    浏览(48)
  • Vue3.0 vue.js.devtools无法显示Pinia调试工具

    之前的配置方式: 更新配置方式: 设置之后即可显示调试工具

    2024年03月11日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包