在构建杂乱的 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 运用。