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

 更新时间:2024年03月07日 08:18:38   作者:慕仲卿  
JavaScript 和 React 提供了灵活的事件处理机制,特别是通过利用事件的捕获阶段来阻止事件传播可以实现精细的权限控制,本文将详细介绍这一技术的应用,并通过实践案例展示如何封装和使用一个 React 鉴权组件,需要的可以参考下

在构建复杂的 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-Router4.0跳转不置顶解决方案

    详解关于React-Router4.0跳转不置顶解决方案

    这篇文章主要介绍了详解关于React-Router4.0跳转不置顶解决案,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-05-05
  • React Redux使用配置详解

    React Redux使用配置详解

    react-redux是redux官方react绑定库,能够使react组件从redux store中读取数据,并且向store分发actions以此来更新数据,这篇文章主要介绍了react-redux的设置,需要的朋友可以参考下
    2022-08-08
  • windows下create-react-app 升级至3.3.1版本踩坑记

    windows下create-react-app 升级至3.3.1版本踩坑记

    这篇文章主要介绍了windows下create-react-app 升级至3.3.1版本踩坑记,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • React的事件处理你了解吗

    React的事件处理你了解吗

    这篇文章主要为大家详细介绍了React的事件处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • react+typescript中使用echarts的实现步骤

    react+typescript中使用echarts的实现步骤

    本文主要介绍了react+typescript中使用echarts的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • react fiber执行原理示例解析

    react fiber执行原理示例解析

    这篇文章主要为大家介绍了react fiber执行原理示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • React Native之TextInput组件解析示例

    React Native之TextInput组件解析示例

    本篇文章主要介绍了React Native之TextInput组件解析示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • 详解React Native网络请求fetch简单封装

    详解React Native网络请求fetch简单封装

    本篇文章主要介绍了详解React Native网络请求fetch简单封装,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • 模块化react-router配置方法详解

    模块化react-router配置方法详解

    这篇文章主要介绍了模块化react-router配置方法详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-06-06
  • React Hook用法示例详解(6个常见hook)

    React Hook用法示例详解(6个常见hook)

    这篇文章主要介绍了React Hook用法详解(6个常见hook),本文通过实例代码给大家介绍了6个常见hook,需要的朋友可以参考下
    2021-04-04

最新评论