详解如何封装和使用一个React鉴权组件

 更新时间:2024年03月07日 08:18:38   作者:慕仲卿  
JavaScript?和?React?提供了灵活的事件处理机制,特别是通过利用事件的捕获阶段来阻止事件传播可以实现精细的权限控制,本文将详细介绍这一技术的应用,并通过实践案例展示如何封装和使用一个?React?鉴权组件,需要的可以参考下
(福利推荐:【腾讯云】服务器最新限时优惠活动,云服务器1核2G仅99元/年、2核4G仅768元/3年,立即抢购>>>:9i0i.cn/qcloud

(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun

在构建复杂的 Web 应用时,经常会遇到需要基于用户权限来控制元素事件访问性的情况。这不仅涉及到用户体验的提升,更关乎应用安全性的加固。JavaScript 和 React 提供了灵活的事件处理机制,特别是通过利用事件的捕获阶段来阻止事件传播可以实现精细的权限控制。本文将详细介绍这一技术的应用,并通过实践案例展示如何封装和使用一个 React 鉴权组件。

1. 在事件的捕获阶段阻止事件的传播

为了更好地理解如何在捕获阶段阻止事件的传播,让我们先从一个完整的 HTML 页面示例开始:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Event Capture and Authorization</title>
    <style>
        .container { padding: 20px; background-color: #f0f0f0; }
        .button { padding: 10px; background-color: #007bff; color: white; cursor: pointer; }
    </style>
</head>
<body>

<div class="container" id="container">
    Click Me
    <div class="button" id="button">Authorized Action</div>
</div>

<script>
    document.getElementById('container').addEventListener('click', function(event) {
        alert('Container clicked!');
    }, true); // Use capture phase

    document.getElementById('button').addEventListener('click', function(event) {
        event.stopPropagation(); // Stop event from reaching the container
        alert('Button clicked!');
    }, false); // Use bubble phase
</script>

</body>
</html>

在这个示例中,我们有一个容器和一个按钮。当按钮在没有授权的情况下被点击时,我们通过在捕获阶段为容器添加的事件监听器中调用 event.stopPropagation() 方法,阻止了事件向上传播。这样,即使按钮被点击,容器的点击事件也不会被触发,从而实现了基于权限的事件控制。

2. 阻止事件传播的意义

阻止事件在捕获阶段的传播不仅是一个技术行为,它背后的意义更加深远。首先,从安全性角度考虑,这可以防止未授权的用户触发敏感操作,如删除数据、修改配置等,从而有效地防范安全风险。其次,从用户体验角度来看,合理地控制事件传播可以避免用户误操作,尤其是在复杂的交互设计中,能够确保应用的操作逻辑更加清晰和稳定。最后,这种机制还提供了一种灵活的事件管理方式,使开发者能够更精细地控制应用的行为和响应,增强了应用的可维护性和扩展性。

3. 封装一个鉴权组件

在构建React前端应用时,确保用户在执行特定操作前已通过身份验证是常见需求。React 提供了灵活的方式来处理这种情况,特别是结合事件捕获机制。以下是如何逐步封装一个利用事件捕获机制进行用户鉴权的 React 组件的详细解释。

3.1 使用 useRef 创建引用

const ref = useRef(null);

useRef 是一个 React 钩子(Hook),它创建了一个可变的 ref 对象,并将其赋值为 null。这个 ref 对象可以被附加到 React 元素上,允许我们直接访问 DOM 元素。在我们的鉴权组件中,这使得我们能够直接在 DOM 元素上添加和移除事件监听器。

3.2 定义事件监听器并在捕获阶段注册

useEffect(() => {
    const handleClickCapture = (e) => {
        if(disabled) return;
        if(!isUserLogin(window.loginInfo && window.loginInfo.userInfo)) {
            e.stopPropagation();
            Modal.clear();
            Modal.confirm({
                bodyClassName: "modal-confirm-body",
                content: intl.get("helptext_login_first"),
                cancelText: intl.get("text_cancel"),
                confirmText: intl.get("text_log_in"),
                onConfirm: () => native_LoginAgain.call()
            });
        }
    };

    const currentElement = ref.current;
    currentElement.addEventListener('click', handleClickCapture, true);

    return () => {
        currentElement.removeEventListener('click', handleClickCapture, true);
    };
}, [disabled]);

useEffect 钩子内,我们定义了一个 handleClickCapture 函数,该函数会在点击事件发生时被调用。通过设置 addEventListener 的第三个参数为 true,我们指示浏览器在捕获阶段触发此监听器,而不是冒泡阶段。这使我们能够在事件向下传播到目标元素之前拦截它。

如果组件被标记为 disabledhandleClickCapture 函数会立即返回,不执行任何操作。如果用户未登录(通过 isUserLogin 函数检查),函数会调用 e.stopPropagation() 阻止事件进一步传播,然后显示一个模态框(Modal),提示用户登录。

useEffect 的清理函数确保在组件卸载时移除事件监听器,防止内存泄漏。

3.3 组件渲染

return (
    <div
        ref={ref}
        className={className}
        style={style}
        onClick={(e) => {
            if (!disabled && isUserLogin(window.loginInfo && window.loginInfo.userInfo)) {
                onClick && onClick(e);
            }
        }}
    >
        {children}
    </div>
);

在组件的返回语句中,我们将 ref 对象附加到 div 元素上。这样,之前定义的事件监听器就能够被正确注册到这个 div 上。我们还为这个 div 提供了一个 onClick 事件处理函数。在这个函数内部,如果组件未被禁用并且用户已登录,则调用传入的 onClick 回调。这保留了组件原有点击行为的可能性,但只在用户满足特定条件时触发。

小结

通过这种方式,就封装了一个可以在事件的捕获阶段根据用户登录状态决定是否允许事件进一步传播的 React 组件。这种模式不仅增强了应用的安全性,避免了未授权的操作,还提高了用户体验,通过模态框提示需要登录。这种鉴权组件的封装展示了 React 以及现代 JavaScript 提供的强大能力,使得开发高质量的 Web 应用更加高效和灵活。

完整组件代码

import React, { useEffect, useRef } from "react";
import { isUserLogin } from "../lib/common";
import { Modal } from "antd-mobile";
import intl from "react-intl-universal";
import { native_LoginAgain } from "../lib/nativeUtil";

export default function LoginAuth(props) {
    const { disabled, onClick, style, className, children } = props;
    const ref = useRef(null); // 使用 useRef 创建一个 ref 对象

    useEffect(() => {
        // 定义一个在捕获阶段执行的 handleClick 函数
        const handleClickCapture = (e) => {
            if(disabled) return;
            if(!isUserLogin(window.loginInfo && window.loginInfo.userInfo)) {
                e.stopPropagation(); // 阻止事件在捕获阶段继续传播
                Modal.clear();
                Modal.confirm({
                    bodyClassName: "modal-confirm-body",
                    content: intl.get("helptext_login_first"),
                    cancelText: intl.get("text_cancel"),
                    confirmText: intl.get("text_log_in"),
                    onConfirm: () => native_LoginAgain.call()
                });
            }
        };

        // 获取当前 ref 指向的 DOM 元素
        const currentElement = ref.current;
        // 为该元素添加捕获阶段的事件监听器
        currentElement.addEventListener('click', handleClickCapture, true);

        // 清理函数:组件卸载时移除事件监听器
        return () => {
            currentElement.removeEventListener('click', handleClickCapture, true);
        };
    }, [disabled]); // 依赖项数组中的元素会触发 useEffect 的重新执行

    return (
        <div
            ref={ref} // 将 ref 绑定到 div 元素上
            className={className}
            style={style}
            onClick={(e) => {
                // 阻止冒泡阶段的处理,如果需要
                if (!disabled && isUserLogin(window.loginInfo && window.loginInfo.userInfo)) {
                    onClick && onClick(e);
                }
            }}
        >
            {children}
        </div>
    );
}

结尾

通过在事件的捕获阶段阻止事件传播,结合 React 组件的封装,不仅能够有效控制应用中的权限逻辑,还能提升用户体验和应用安全性。这种技术的应用展示了现代前端开发中,事件处理机制的强大能力,以及通过合理设计提高应用整体质量的可能性。在开发实践中灵活运用这一技术,将有助于构建更加稳定、安全且用户友好的 Web 应用。

到此这篇关于详解如何封装和使用一个React鉴权组件的文章就介绍到这了,更多相关React鉴权组件内容请搜索程序员之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持程序员之家!

相关文章

  • React如何将组件渲染到指定DOM节点详解

    React如何将组件渲染到指定DOM节点详解

    这篇文章主要给大家介绍了关于React如何将组件渲染到指定DOM节点的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习下吧。
    2017-09-09
  • 利用React高阶组件实现一个面包屑导航的示例

    利用React高阶组件实现一个面包屑导航的示例

    这篇文章主要介绍了利用React高阶组件实现一个面包屑导航的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • React?Streaming?SSR原理示例深入解析

    React?Streaming?SSR原理示例深入解析

    这篇文章主要为大家介绍了React?Streaming?SSR原理示例深入解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • create-react-app 修改为多入口编译的方法

    create-react-app 修改为多入口编译的方法

    这篇文章主要介绍了create-react-app 修改为多入口编译的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • Redux中间件的使用方法教程

    Redux中间件的使用方法教程

    中间件就是一个函数,对store.dispatch方法进行了改造,在发出 Action 和执行 Reducer 这两步之间,添加了其他功能,要理解中间件,关键点是要知道,这个中间件是连接哪些部分的软件,它在中间做了什么事,提供了什么服务
    2023-01-01
  • React-native桥接Android原生开发详解

    React-native桥接Android原生开发详解

    本篇文章主要介绍了React-native桥接Android原生开发详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • react 报错Module build failed: BrowserslistError: Unknown browser query `dead`问题的解决方法

    react 报错Module build failed: Browserslis

    这篇文章主要介绍了react 报错Module build failed: BrowserslistError: Unknown browser query `dead`问题的解决方法,需要的朋友可以参考下
    2023-06-06
  • 详解vant2 自动检查表单验证 -validate

    详解vant2 自动检查表单验证 -validate

    这篇文章主要介绍了vant2 自动检查表单验证 -validate,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-10-10
  • React项目中报错:Parsing error: The keyword 'import' is reservedeslint的问题及解决方法

    React项目中报错:Parsing error: The keyword &a

    ESLint 默认使用的是 ES5 语法,如果你想使用 ES6 或者更新的语法,你需要在 ESLint 的配置文件如:.eslintrc.js等中设置 parserOptions,这篇文章主要介绍了React项目中报错:Parsing error: The keyword 'import' is reservedeslint的问题及解决方法,需要的朋友可以参考下
    2023-12-12
  • React组件通信实现流程详解

    React组件通信实现流程详解

    这篇文章主要介绍了React组件通信,在开发中组件通信是React中的一个重要的知识点,本文通过实例代码给大家讲解react中常用的父子、跨组件通信的方法,需要的朋友可以参考下
    2022-12-12

最新评论

?


http://www.vxiaotou.com