为了账号安全,请及时绑定邮箱和手机立即绑定

React中的设计模式详解

基于专家建议,翻译调整如下:
基于专家的建议,“引言”可以更口语化地翻译成“开场白”或简单的“介绍”,以匹配“Introduction”的非正式语气。
为了保持原文的简洁直接,翻译中不应添加原文中不存在的任何不必要的语言元素。

#

介绍

#

设计模式为软件开发中常见的问题提供了标准化的解决方案。在 React 中,利用设计模式可以构建出更可扩展、更易于维护和更高效的应用程序。本文将深入探讨一些在 React 中常用的设计模式,包括容器组件与展示组件模式、高阶组件(HOC)模式、渲染属性模式以及自定义钩子模式。每个模式都将通过现代 React 钩子进行说明。

1. 容器和展示组件设计模式

概念说明:这种模式将组件分为两类:容器组件(也称为智能组件),负责管理状态和逻辑处理;和展示组件(也称为哑组件),负责界面渲染。

好处:

  • 关注点分离:将业务逻辑与UI渲染分开。
  • 可重用性:呈现组件可以在应用程序的不同地方重复利用。

实施

容器组件

    // TodoContainer.js
    import React, { useState, useEffect } from 'react';
    import TodoList from './TodoList';

    const TodoContainer = () => {
        const [todos, setTodos] = useState([]);
        useEffect(() => {
            fetch('/api/todos')
                .then(response => response.json())
                .then(data => setTodos(data));
        }, []);
        return <TodoList todos={todos} />;
    };
    export default TodoContainer;

展示组件

    // TodoList.js
    import React from 'react';

    const TodoList = ({ todos }) => (
        <ul>
            {todos.map(todo => (
                <li key={todo.id}>{todo.text}</li>
            ))}
        </ul>
    );
    export default TodoList;
2. 高阶组件 (HOC) 模式:

概念说明:高级组件是一个函数,它接收一个组件作为参数,并返回一个带有新特性的组件,该组件带有额外属性和行为。

好处有:

  • 代码重用性:封装可以跨多个组件共享的通用行为。
  • 增强功能:允许组件通过添加额外功能来增强。

实施

import React, { useEffect } from 'react';

const withLogging = WrappedComponent => {
  return props => {
    useEffect(() => {
      console.log('组件已加载');
    }, []);
    return <WrappedComponent {...props} />;
  };
};
export default withLogging;
// MyComponent.js
import React from 'react';
import withLogging from './withLogging';

const MyComponent = () => <div>嗨,世界!</div>;
export default withLogging(MyComponent);
3. 渲染道具模式

概念:此模式通过使用作为函数的 prop 在组件间共享代码片段。

好处有:

  • 灵活性:允许将动态行为传递给组件。
  • 可重用性:通过将函数作为属性传递来增强代码的可重用性。

实施

    // 鼠标跟踪器.js  
    import React, { useState } from 'react';  

    const MouseTracker = ({ render }) => {  
        const [position, setPosition] = useState({ x: 0, y: 0 });  
        const handleMouseMove = event => {  
            setPosition({  
                x: event.clientX,  
                y: event.clientY  
            });  
        };  
        return (  
            <div style={{ height: '100vh' }} onMouseMove={handleMouseMove}>  
                {render(position)}  
            </div>  
        );  
    };  
    export default MouseTracker;
// App.js
import React from 'react';
import MouseTracker from './MouseTracker';

const App = () => (
    <MouseTracker render={({ x, y }) => (
        <h1>鼠标的当前位置是 ({x}, {y})</h1>
    )} />
);
export default App;
4. 自定义钩模式

想法:自定义钩子允许你将逻辑和状态管理打包成可以重复利用的函数。

好处

  • 代码复用性:通过复用多个组件间的逻辑来提高代码的复用性。
  • 简化:通过将复杂逻辑移至钩子来简化组件逻辑。

实现步骤:Copy code

    // useFetchData.js
    import { useState, useEffect } from 'react';

    const useFetchData = url => {
        const [data, setData] = useState(null);
        useEffect(() => {
            fetch(url)
                .then(response => response.json())
                .then(data => setData(data));
        }, [url]);
        return data;
    };
    export default useFetchData;
    // DataDisplay.js  
    import React from 'react';  
    import useFetchData from './useFetchData';  

    const DataDisplay = ({ url }) => {  
        const data = useFetchData(url);  
        return data ? <pre>{JSON.stringify(data, null, 2)}</pre> : <p>正在加载...</p>;  
    };  
    export default DataDisplay;
5. 复合组件做法

概念:组件复合模式允许你将组件组合在一起,形成一个统一的单元,其中每个组件都为更大的目标服务。

好处:

  • 封装:组件可以无缝协作,同时各自保持独立的职责。
  • 灵活性:用户可以通过自定义复合组件的各个部分来调整其行为和外观。

实施

    // Toggle.js
    // 这是一个切换组件,用于处理子元素的状态切换
    import React, { useState } from 'react';

    const 开关 = ({ children }) => {  // 这里定义了一个开关组件,接收children作为参数
        const [开启, 设置开启] = useState(false);  // 定义一个状态变量开启,用于控制组件的开关状态
        const 切换 = () => {  // 定义一个切换函数,用于改变开启的状态
            设置开启(!开启);  // 切换开启的状态
        };
        const 获取子元素属性 = () => {  // 定义一个获取子元素属性的函数
            return {  // 返回子元素需要的属性
                开启,
                切换,
            };
        };
        return <>{React.Children.map(children, child => React.cloneElement(child, 获取子元素属性()))}</>;  // 遍历子元素,并为每个子元素添加获取子元素属性函数返回的属性
    };
    export default 开关;
    // ToggleButton.js  
    import React from 'react';  

    const 切换按钮 = ({ on, toggle }) => (  
        <button onClick={toggle}>{on ? '关掉' : '开启'}</button>  
    );  
    export default 切换按钮;  
// ToggleMessage.js  
import React from 'react';  

const ToggleMessage = ({ on }) => (  
    <p>{on ? '按钮处于开启状态' : '按钮处于关闭状态'}</p>  
);  
export default ToggleMessage;  
    // App.js  
    import React from 'react';  
    import Toggle from './Toggle';  
    import ToggleButton from './ToggleButton';  
    import ToggleMessage from './ToggleMessage';  
    const App = () => (  
        <Toggle>  
            <ToggleButton />  
            <ToggleMessage />  
        </Toggle>  
    );  
    export default App;
  • 切换组件:管理状态(开或关),并通过复合组件模式向其子组件提供一个切换函数。
  • 切换按钮组件:接收on状态和toggle函数作为属性,处理点击事件并显示相应文本。
  • 切换消息组件:接收on状态并根据当前状态显示相应消息。

这种模式允许 ToggleButtonToggleMessageToggle 管理下无缝配合,体现了复合组件模式的封装性与灵活性。

结束语

在 React 中理解和应用带有钩子(hooks)的设计模式可以显著提高应用程序的可扩展性、可维护性和效率。通过利用容器组件和展示组件、高阶组件(Higher-Order Components)、渲染属性(Render Props)、复合组件(Compound Components)和自定义钩子(Custom Hooks)等模式,你可以创建模块化且可重用的代码,符合最佳实践。试着用这些模式试试看,看看你的 React 项目会变得多好。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消