ReactJS 设计模式:编写健壮且可扩展的组件

news/2024/9/21 15:51:07
reactjs 中的设计模式为应用程序开发中的常见问题提供了标准化且经过验证的解决方案。使用这些模式不仅使您的代码更具可读性和可维护性,而且还增强了其可扩展性和健壮性。让我们深入研究一些最流行的 reactjs 设计模式,并通过示例来说明它们的用法。 1. 容器和表示组件模式容器和展示模式将组件分为两类:展示组件:关注事物的外观(ui)。容器组件:关注事物如何工作(逻辑和状态管理)。这种分离可以实现更好的可重用性、更容易的测试和更清晰的代码。示例:展示和容器组件// presentational component: displaying user list (userlist.js)import react from 'react';const userlist = ({ users }) =&gt; ( 登录后复制 {users.map((user) => ( {user.name} ))} );export default userlist;// container component: fetching user data (usercontainer.js)import react, { usestate, useeffect } from 'react';import userlist from './userlist';const usercontainer = () =&gt; { const [users, setusers] = usestate([]); useeffect(() =&gt; { const fetchusers = async () =&gt; { const response = await fetch('https://jsonplaceholder.typicode.com/users'); const data = await response.json(); setusers(data); }; fetchusers(); }, []); return <userlist users="{users}"></userlist>;};export default usercontainer;登录后复制这里,userlist 是一个展示组件,它接收用户作为 props,而 usercontainer 则处理数据获取和状态管理。 2. 高阶组件(hoc)模式a 高阶组件 (hoc) 是一个将组件作为参数并返回新组件的函数。 hoc 通常用于横切关注点,例如身份验证、日志记录或增强组件行为。示例:创建 hoc 进行授权// withauthorization.js (hoc for authorization)import react from 'react';const withauthorization = (wrappedcomponent) =&gt; { return class extends react.component { componentdidmount() { if (!localstorage.getitem('authtoken')) { // redirect to login if not authenticated window.location.href = '/login'; } } render() { return <wrappedcomponent></wrappedcomponent>; } };};export default withauthorization;登录后复制// dashboard.js (component wrapped with hoc)import react from 'react';import withauthorization from './withauthorization';const dashboard = () =&gt; <h1>welcome to the dashboard</h1>;export default withauthorization(dashboard);登录后复制通过使用 withauthorization 包装 dashboard,您可以确保只有经过身份验证的用户才能访问它。 3. 渲染道具模式render props 模式涉及使用值为函数的 prop 在组件之间共享代码。此模式对于基于特定条件或状态的动态渲染非常有用。示例:使用渲染道具进行鼠标跟踪// mousetracker.js (component with render props)import react, { usestate } from 'react';const mousetracker = ({ render }) =&gt; { const [position, setposition] = usestate({ x: 0, y: 0 }); const handlemousemove = (event) =&gt; { setposition({ x: event.clientx, y: event.clienty }); }; return <div onmousemove="{handlemousemove}">{render(position)}</div>;};export default mousetracker;登录后复制// app.js (using render props)import react from 'react';import mousetracker from './mousetracker';const app = () =&gt; ( <mousetracker render="{({" x y> ( <h1> mouse position: ({x}, {y}) </h1> )} /&gt;);export default app;</mousetracker>登录后复制mousetracker 组件使用 render prop 将鼠标位置数据传递给任何组件,使其具有高度可重用性。 4. 自定义挂钩模式自定义 hook 允许您跨多个组件封装和重用有状态逻辑。这种模式促进了代码的可重用性和清晰的关注点分离。示例:创建用于获取数据的自定义挂钩// usefetch.js (custom hook)import { usestate, useeffect } from 'react';const usefetch = (url) =&gt; { const [data, setdata] = usestate(null); const [loading, setloading] = usestate(true); useeffect(() =&gt; { const fetchdata = async () =&gt; { const response = await fetch(url); const result = await response.json(); setdata(result); setloading(false); }; fetchdata(); }, [url]); return { data, loading };};export default usefetch;登录后复制// app.js (using the custom hook)import react from 'react';import usefetch from './usefetch';const app = () =&gt; { const { data, loading } = usefetch('https://jsonplaceholder.typicode.com/posts'); if (loading) return <div>loading...</div>; return ( 登录后复制 {data.map((post) => ( {post.title} ))} );};export default app;usefetch 自定义钩子封装了数据获取逻辑,可以在不同组件之间复用。 5. 复合组件模式复合组件模式允许组件一起工作来管理状态和行为。此模式对于构建复杂的 ui 组件(如选项卡、手风琴或下拉菜单)非常有用。示例:使用复合组件构建选项卡// tabs.js (parent component)import react, { usestate } from 'react';const tabs = ({ children }) =&gt; { const [activeindex, setactiveindex] = usestate(0); return react.children.map(children, (child, index) =&gt; react.cloneelement(child, { isactive: index === activeindex, setactiveindex, index }) );};const tab = ({ children, isactive, setactiveindex, index }) =&gt; ( <button onclick="{()"> setactiveindex(index)}&gt;{children}</button>);const tabpanel = ({ children, isactive }) =&gt; (isactive ? <div>{children}</div> : null);tabs.tab = tab;tabs.tabpanel = tabpanel;export default tabs;登录后复制// app.js (using compound components)import react from 'react';import tabs from './tabs';const app = () =&gt; ( <tabs><tabs.tab>tab 1</tabs.tab><tabs.tab>tab 2</tabs.tab><tabs.tabpanel>content for tab 1</tabs.tabpanel><tabs.tabpanel>content for tab 2</tabs.tabpanel></tabs>);export default app;登录后复制tabs 组件管理状态,而 tab 和 tabpanel 组件协同显示选项卡内容。 6. 受控和非受控组件模式受控组件完全由 react 状态管理,而非受控组件则依赖 dom 来获取状态。两者都有其用途,但为了一致性和可维护性,受控组件通常是首选。示例:受控组件与不受控组件// controlled component (textinputcontrolled.js)import react, { usestate } from 'react';const textinputcontrolled = () =&gt; { const [value, setvalue] = usestate(''); return ( <input type="text" value="{value}" onchange="{(e)"> setvalue(e.target.value)} /&gt; );};export default textinputcontrolled;登录后复制// uncontrolled component (textinputuncontrolled.js)import react, { useref } from 'react';const textinputuncontrolled = () =&gt; { const inputref = useref(); const handleclick = () =&gt; { console.log(inputref.current.value); }; return ( <input type="text" ref="{inputref}"><button onclick="{handleclick}">log input value</button> &gt; );};export default textinputuncontrolled;登录后复制在受控组件中,react 完全控制表单状态,而在非受控组件中,状态由 dom 本身管理。 7. 钩子工厂模式hooks 工厂模式涉及创建动态生成和管理多个状态或行为的钩子,提供灵活的方式来管理复杂逻辑。示例:使用 hooks factory 进行动态状态管理// usedynamicstate.js (hook factory)import { usestate } from 'react';const usedynamicstate = (initialstates) =&gt; { const states = {}; const setters = {}; initialstates.foreach(([key, initialvalue]) =&gt; { const [state, setstate] = usestate(initialvalue); states[key] = state; setters[key] = setstate; }); return [states, setters];};export default usedynamicstate;登录后复制// App.js (Using the Hooks Factory)import React from 'react';import useDynamicState from './useDynamicState';const App = () =&gt; { const [states, setters] = useDynamicState([ ['name', ''], ['age', 0], ]); return ( <div> <input type="text" value="{states.name}" onchange="{(e)"> setters.name(e.target.value)} /&gt; <input type="number" value="{states.age}" onchange="{(e)"> setters.age(parseInt(e.target.value))} /&gt; <p>Name: {states.name}</p> <p>Age: {states.age}</p> </div> );};export default App;登录后复制这个钩子工厂动态创建和管理多个状态,提供灵活性和更简洁的代码。 结论通过利用这些设计模式,您可以创建更健壮、可扩展和可维护的 react 应用程序。这些模式可帮助您编写符合最佳实践的干净、可重用的代码,确保您的应用程序随着时间的推移更容易开发和管理。您想更深入地研究这些模式或探索其他主题吗? 以上就是ReactJS 设计模式:编写健壮且可扩展的组件的详细内容,更多请关注我的其它相关文章!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/62968.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

基于IDF的ESP32S3-LVGL DEMO移植

简介 ESP32-32出色的性价比,较好的性能与内存空间,可以好利用来完成GUI显示库的加载 LVGL LVGL是一款比较流行的致力于MCU与MPU创建漂亮UI的嵌入式图形库,免费且开源。 硬件 硬件采用的是正点原子的ESP32-S3 屏幕使用的是SPI通信方式,配合IO口控制(RST,A0),来实现LCD屏幕…

nginx: 按ip地址限流

一,以固定的速度提供服务 语法: 例子 limit_req_zone $binary_remote_addr zone=test:10m rate=2r/s;server { location / { limit_req zone=test; }} 语法: imit_req_zone 用于设置限流和共享内存区域的参数,格式为: limit_req_zone key zone rate。 key: 定…

Free5GC源码研究(2) - 单个NF的软件架构

前文我们总览了free5gc的总体软件架构。整一个free5gc系统又由几个NF(Network Function)组成,所以本文继续深入研究单个NF的软件架构。要研究NF的软件架构,最直接的方式是找一个简单的NF来回观摩。free5gc/ausf算是比较简单的一个,然而我发现了一个更简单的NF,叫做andy89…

一,初始 MyBatis-Plus

一,初始 MyBatis-Plus @目录一,初始 MyBatis-Plus1. MyBatis-Plus 的概述2. 入门配置第一个 MyBatis-Plus 案例3. 补充说明:3.1 通用 Mapper 接口介绍3.1.1 Mapper 接口的 “增删改查”3.1.1.1 查询所有记录3.1.1.2 插入一条数据3.1.1.3 删除一条数据3.1.1.4 更新一条数据3.…

[神经网络与深度学习笔记]LDA降维

LDA降维 LinearDiscriminant Analysis 线性判别分析,是一种有监督的线性降维算法。与PCA保持数据信息不同,LDA的目标是将原始数据投影到低维空间,尽量使同一类的数据聚集,不同类的数据尽可能分散 步骤:计算类内散度矩阵\(S_b\) 计算类间散度矩阵\(S_w\) 计算矩阵\(S_w^{-1…

C++ 指针和迭代器支持的操作

▲ 《C++ Primer》 P96 指针也都支持上面的操作。

代码整洁之道--读书笔记(14)

代码整洁之道简介: 本书是编程大师“Bob 大叔”40余年编程生涯的心得体会的总结,讲解要成为真正专业的程序员需要具备什么样的态度,需要遵循什么样的原则,需要采取什么样的行动。作者以自己以及身边的同事走过的弯路、犯过的错误为例,意在为后来者引路,助其职业生涯迈上更…

hexo安装后报错hexo 不是内部或外部命令,也不是可运行的程序 或批处理文件。

hexo问题 之前利用hexo和gitee搭建了一个博客,但是最近gitee的gitpage停止服务了,便想着在github上搭建一个。 在到安装hexo这一步的时候,一直报错hexo 不是内部或外部命令,也不是可运行的程序 或批处理文件。 我的所有安装步骤和环境变量发现都没有错,反复配置后去找了一…