超级实用!React-Router v6实现页面级按钮权限
<p>大家好,我是王天~</p><p>今天咱们用 reac+reactRouter来实现页面级的按钮权限功能。这篇文章分三部分,实现思路、代码实现、踩坑记录。</p>
<p>嫌啰嗦的朋友,直接拖到第二章节看代码哦。</p>
<h1 id="前言">前言</h1>
<p>通常情况下,咱们为用户添加权限时,除了页面权限,还会细化到按钮级别,比如、新增、删除、查看等权限。</p>
<p>如下效果,切换用户登录后,操作权限除了左侧菜单,还有页面按钮。<br>
<img src="https://img2023.cnblogs.com/other/2066039/202310/2066039-20231003201210436-74037476.gif"></p>
<h1 id="实现思路">实现思路</h1>
<p>按钮控制本质是条件判断,满足条件显示按钮,否则禁用/消失。<br>
假如每个页面的按钮权限都不同,简单的条件判断,肯定无法满足,那如何实现呢 ?<br>
王天觉得重点是权限数据结构,如何获取当前页面的按钮权限数据,这需要和后端沟通好,定义页面路径和权限数据的映射关系</p>
<h2 id="使用路由实现页面按钮权限">使用路由实现页面按钮权限</h2>
<p><strong>步骤:</strong></p>
<ol>
<li>在路由配置中添加页面权限参数</li>
<li>通过路由实例,获取当前页的权限</li>
<li>封装按钮权限组件,动态显隐按钮</li>
</ol>
<h1 id="实战代码">实战代码</h1>
<h2 id="定义路由配置数据">定义路由配置数据</h2>
<p>需和后端配合,将按钮权限和页面路由一同返回<br>
<img src="https://img2023.cnblogs.com/other/2066039/202310/2066039-20231003201218195-579706631.png"></p>
<h2 id="存储路由和按钮权限映射关系">存储路由和按钮权限映射关系</h2>
<p>既然无法通过路由实例获取权限数据,那么我们手动创建一个对象,来存储路由和按钮权限映射关系。<br>
用户登录后,在遍历生成路由配置同时、将按钮权限和页面路径的映射数据,存储本地。<br>
执行如下代码<br>
<img src="https://img2023.cnblogs.com/other/2066039/202310/2066039-20231003201220877-1861410527.png"></p>
<h2 id="按钮权限组件">按钮权限组件</h2>
<p>封装按钮权限组件,读取本地权限数据、控制按钮的显隐、禁用状态,代码如下:</p>
<pre><code class="language-tsx">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){
returnprops.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;
</code></pre>
<h2 id="使用按钮权限组件">使用按钮权限组件</h2>
<pre><code class="language-tsx"><AuthButton scopeTtype="isDelete">
<Button type="primary" onClick={start} disabled={!hasSelected} loading={loading}>
批量删除
</Button>
</AuthButton>
<AuthButton scopeTtype="isAdd">
<Button onClick={showModal}>新增员工</Button>
</AuthButton>
</code></pre>
<p>模拟的路由数据:员工管理页面的路由、按钮配置<br>
<img src="https://img2023.cnblogs.com/other/2066039/202310/2066039-20231003201221669-477069020.png"></p>
<h2 id="效果">效果:</h2>
<p>当切换用户登录后,很明细发现右侧表格、操作按钮权限变化。效果如下<br>
<img src="https://img2023.cnblogs.com/other/2066039/202310/2066039-20231003201240894-2068149058.gif"><br>
以上全文完,最后总结一下reactRoute和vueRouter的实现区别。</p>
<h2 id="vuerouter-vs-reactrouter">vueRouter vs ReactRouter</h2>
<h3 id="vuerouter">vueRouter</h3>
<p>此方案中,在vue中实现比较方便,使用vueRouter配置路由<code>meta</code>元信息、为按钮权限的数据</p>
<pre><code class="language-tsx">{
path: '/imgMove/:id',
name: 'imgMove',
meta: {
itwangtianAuth: true
// 此页面是否token校验
},
component: imgMove
}
</code></pre>
<p>在页面路由实例中读取meta数据,进行页面级别的按钮权限控制。</p>
<pre><code class="language-javascript">// 在 Vue 组件中获取路由的 meta 数据
export default {
name: 'ExampleComponent',
mounted() {
// 获取当前路由对应的路由记录
const route = this.$route;
// 获取该路由记录的 meta 数据
const meta = route.meta;
// 使用 meta 数据
console.log(meta.itwangtianAuth);
}
}
</code></pre>
<h3 id="reactrouter">ReactRouter</h3>
<p>但是,在react-Router6版本中没有路由元信息配置,就算自定义路由属性,也无法获取,如下是踩坑代码,大家看看就行、可不要尝试了</p>
<h2 id="踩坑记录">踩坑记录</h2>
<p>踩坑代码-添加路由自定义属性,获取权限数据首先,在路由配置中设置自定义属性,例如 title 和 requiresAuth:</p>
<pre><code class="language-tsx"><Route
path="/dashboard"
element={<Dashboard />}
title="Dashboard"
requiresAuth={true}
/>
</code></pre>
<p>然后,在 Dashboard 组件中可以通过 useRoutes() 钩子获取路由传递的属性,如下所示:</p>
<pre><code class="language-tsx">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>
);
}
</code></pre>
<p>结果不用说了,报错啊啊啊啊啊啊啊<br>
在react-route6中 无法自定义路由属性,报错日志如下<br>
<img src="https://img2023.cnblogs.com/other/2066039/202310/2066039-20231003201246746-1109593516.png"></p>
<p>感谢阅完~</p>
<p>读者朋友好呀,我是王天~</p>
<p>尝试做过很多事情,汽修专业肄业生,半路出道的野生程序员、前端讲师、新手作者,最终还是喜欢写代码、乐于用文字记录热衷分享~</p>
<p>如文章有错误或者不严谨的地方,期待给于指正,万分感谢。</p>
<p>如果喜欢或者 有所启发,欢迎 star,对作者也是一种鼓励。</p>
<p>微信:「<code>wangtian3111</code>」,加我进王天唯一的读者群。</p>
<p>个人博客:https://itwangtian.com</p>
</div>
<div id="MySignature" role="contentinfo">
95后、自学编程工作3年、向上生长<br><br>
来源:https://www.cnblogs.com/wangtianzhen/p/17741594.html
頁:
[1]