超级实用!React-Router v6实现页面级按钮权限

大家好,我是王天~

今天咱们用 reac+reactRouter来实现页面级的按钮权限功能。这篇文章分三部分,实现思路、代码实现、踩坑记录。

嫌啰嗦的朋友,直接拖到第二章节看代码哦。

前言

通常情况下,咱们为用户添加权限时,除了页面权限,还会细化到按钮级别,比如、新增、删除、查看等权限。

如下效果,切换用户登录后,操作权限除了左侧菜单,还有页面按钮。

超级实用!React-Router v6实现页面级按钮权限

实现思路

按钮控制本质是条件判断,满足条件显示按钮,否则禁用/消失。
假如每个页面的按钮权限都不同,简单的条件判断,肯定无法满足,那如何实现呢 ?
王天觉得重点是权限数据结构,如何获取当前页面的按钮权限数据,这需要和后端沟通好,定义页面路径和权限数据的映射关系

使用路由实现页面按钮权限

步骤:

  1. 在路由配置中添加页面权限参数
  2. 通过路由实例,获取当前页的权限
  3. 封装按钮权限组件,动态显隐按钮

实战代码

定义路由配置数据

需和后端配合,将按钮权限和页面路由一同返回

超级实用!React-Router v6实现页面级按钮权限

存储路由和按钮权限映射关系

既然无法通过路由实例获取权限数据,那么我们手动创建一个对象,来存储路由和按钮权限映射关系。
用户登录后,在遍历生成路由配置同时、将按钮权限和页面路径的映射数据,存储本地。
执行如下代码

超级实用!React-Router v6实现页面级按钮权限

按钮权限组件

封装按钮权限组件,读取本地权限数据、控制按钮的显隐、禁用状态,代码如下:

import { Tooltip } from 'antd';
import React from 'react';
import { useLocation } from 'react-router-dom';

interface IndexProps {
  scopeTtype:string,// 权限码
  children:any// 子组件
}

const Index: React.FC<IndexProps> = (props) => {
  // 获取当前页面的位置信息、
  const routeDom = useLocation(); 
  // 从本地缓存读取 页面路径和权限数据
  const strPersstion = localStorage.getItem('pagePersstion');
  const pagePersstion = JSON.parse(strPersstion as string); 
  // 找到当前页的按钮权限数据
  const currentPerssion = pagePersstion.find((item: { page: string; })=>item.page == routeDom.pathname);
  console.log('当前页面的按钮权限',currentPerssion);
  //  有权限返回按钮
  if(currentPerssion.permissions[props.scopeTtype]){
    return  props.children;
  }else{ 
    // 没有则禁用、或者隐藏按钮
    // 要实现按钮禁用,需要设置组件的disabled 
    // 可是react 中的props是只读无法修改,如何修改props中子组件呢?
    // 通过React API React.cloneElement 克隆出新的元素进行修改如下
    const Button = React.cloneElement(props.children,{
      disabled: true
    });

    return   <>
      <Tooltip title="暂无权限">  {Button}</Tooltip>
    </>;
  };
};


export default Index;

使用按钮权限组件

<AuthButton scopeTtype="isDelete">
  <Button type="primary" onClick={start} disabled={!hasSelected} loading={loading}>
    批量删除
  </Button>
</AuthButton>
<AuthButton scopeTtype="isAdd">
    <Button onClick={showModal}>新增员工</Button>
</AuthButton>

模拟的路由数据:员工管理页面的路由、按钮配置

超级实用!React-Router v6实现页面级按钮权限

效果:

当切换用户登录后,很明细发现右侧表格、操作按钮权限变化。效果如下

超级实用!React-Router v6实现页面级按钮权限


以上全文完,最后总结一下reactRoute和vueRouter的实现区别。

vueRouter vs ReactRouter

vueRouter

此方案中,在vue中实现比较方便,使用vueRouter配置路由meta元信息、为按钮权限的数据

{
  path: '/imgMove/:id',name: 'imgMove',meta: {
    itwangtianAuth: true
    // 此页面是否token校验
  },component: imgMove
}

在页面路由实例中读取meta数据,进行页面级别的按钮权限控制。

// 在 Vue 组件中获取路由的 meta 数据
export default {
  name: 'ExampleComponent',mounted() {
    // 获取当前路由对应的路由记录
    const route = this.$route; 
    // 获取该路由记录的 meta 数据
    const meta = route.meta; 
    // 使用 meta 数据
    console.log(meta.itwangtianAuth); 
  }
}

ReactRouter

但是,在react-Router6版本中没有路由元信息配置,就算自定义路由属性,也无法获取,如下是踩坑代码,大家看看就行、可不要尝试了

踩坑记录

踩坑代码-添加路由自定义属性,获取权限数据首先,在路由配置中设置自定义属性,例如 title 和 requiresAuth:

<Route
  path="/dashboard"
  element={<Dashboard />}
  title="Dashboard"
  requiresAuth={true}
  />

然后,在 Dashboard 组件中可以通过 useRoutes() 钩子获取路由传递的属性,如下所示:

import { useRoutes,useParams,useNavigate } from 'react-router-dom';

function Dashboard() {
  const params = useParams();
  const navigate = useNavigate();

  // 访问路由传递的属性
  const { title,requiresAuth } = useRoutes().pathname;

  // 在这里使用元信息进行逻辑处理

  return (
    <div>
      <h1>{title}</h1>
      {/* 组件的其余部分 */}
    </div>
  );
}

结果不用说了,报错啊啊啊啊啊啊啊
在react-route6中 无法自定义路由属性,报错日志如下

超级实用!React-Router v6实现页面级按钮权限

感谢阅完~

读者朋友好呀,我是王天~

尝试做过很多事情,汽修专业肄业生,半路出道的野生程序员、前端讲师、新手作者,最终还是喜欢写代码、乐于用文字记录热衷分享~

如文章有错误或者不严谨的地方,期待给于指正,万分感谢。

如果喜欢或者 有所启发,欢迎 star,对作者也是一种鼓励。

微信:「wangtian3111」,加我进王天唯一的读者群。

个人博客:https://itwangtian.com

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件举报,一经查实,本站将立刻删除。

本文链接:https://www.f2er.com/3188629.html

大家都在看

  • 飞码LowCode前端技术系列:如何便捷快速验证实现投产及飞码探索

    本篇文章从数据中心,事件中心如何协议工作、不依赖环境对vue2.x、vue3.x都可以支持、投产页面问题定位三个方面进行分析。
    2023-11-16 博文
  • 如何优雅使用 vuex

    大纲 本文内容更多的是讲讲使用 vuex 的一些心得想法,所以大概会讲述下面这些点: Q1:我为什么会想使用 vuex 来管理数据状态交互? Q2:使用 vuex 框架有哪些缺点或者说副作用? Q3:我是如何在项目里使用 vuex 的? 初识 vuex 对于 vuex,有人喜欢,有人反感 喜欢的人觉
    2023-11-16 博文
  • 第三方组件及计算属性传参的问题解决方式

    1. 前言 唉,好想玩滋嘣。 2. 计算属性直接传参接收不到 表格数据某一列需要用的计算属性时,模板中使用计算属性 fullName 就会直接调用 fullName 函数,而在模板中 fullName(item) 相当于fullName()(item),此处为函数柯里化。 &lt;el-table-
    2023-11-16 博文
  • 记录--Vue3基于Grid布局简单实现一个瀑布流组件

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前言 在学习Grid布局之时,我发现其是CSS中的一种强大的布局方案,它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局,在刷某书和某宝首页时,我们发现其展示方式就是一种瀑布流,是一种流行的网站页面布局,视觉表……
    2023-11-16 博文
  • 用强数据类型保护你的表单数据-基于antd表单的类型约束

    接口数据类型与表单提交数据类型,在大多数情况下,大部分属性的类型是相同的,但很少能做到完全统一。我在之前的工作中经常为了方便,直接将接口数据类型复用为表单内数据类型,在遇到属性类型不一致的情况时会使用any强制忽略类型错误。后来经过自省与思考,这种工作模式会引起各种隐藏bug,一定有更……
    2023-11-16 博文
  • pinia的使用

    前言 最近新开了个项目,以前老项目都是vue2+vuex开发的,都说用vue3+pinia爽得多,那新项目就vue3+pinia吧。这里记录一下pinia的使用。 使用方法 安装pinia: npm i pinia main.js中引入pinia: //main.js import { create
    2023-11-16 博文
  • 记录--让我们来深入了解一下前端“三清”是什么

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前端“三清” 在前端开发中,我们经常听到关于“三清”的说法,即 window、document、Object。这三者分别代表了 BOM(浏览器对象模型)、DOM(文档对象模型)以及 JS 的顶层对象。在这个体系中,我们通过 JavaScr
    2023-11-16 博文
  • 记录--啊?Vue是有三种路由模式的?

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 众所周知,vue路由模式常见的有 history 和 hash 模式,但其实还有一种方式-abstract模式(了解一哈~) 别急,本文我们将重点逐步了解: 路由 + 几种路由模式 + 使用场景 + 思考 + freestyle 路由概念
    2023-11-16 博文