React开发的设计模式及原则

简介: 设计模式是最常见的,通用问题的可复用解决方案的归纳总结,通常被认为是解决该类问题的最佳实践,使用设计模式能帮助我们写出更容易维护,更健壮的代码。设计模式有很多,通常它们都会遵循一些共同的设计原则,接下来我们一起回顾下React社区里出现过的一些设计模式,以及它们所遵循的设计原则。

介绍

设计模式是对常见的,通用问题的可复用解决方案的归纳总结,通常被认为是解决该类问题的最佳实践,使用设计模式能帮助我们写出更容易维护,更健壮的代码。设计模式有很多,通常它们都会遵循一些共同的设计原则,接下来我们一起回顾下React社区里出现过的一些设计模式,以及它们所遵循的设计原则。

一些设计原则

  1. 单一职责原则(Single-responsibility responsibility) : 每个实体(class, function, module)只应该有一个职责。例如当一个组件接收了太多的props,我们应该考虑组件是不是做了太多的事情,有没有必要进行拆分。
  2. 开闭原则(Open-closed principle):实体(class, function, module) 应该对扩展开放,但是对修改关闭。开闭原则意味着应该存在不直接修改的方式扩展实体的功能。
  3. 依赖反转原则(Dependency inversion principle):依赖于抽象,而不是具体的实现。依赖注入是一种实现依赖反转的方式。
  4. 不要自我重复 (Don't repeat yourself):重复代码会造成代码维护的困难。
  5. Composition over inheritance: 通过组合集成的两个组件是松耦合关系,通过props来约束。但是有继承关系的两个组件是强耦合关系,对父组件的修改可能会导致子组件的未预期的结果。

React设计模式

Container & presentational component

把业务组件划分成container组件和presentational组件。 Presentational component中负责组件的ui渲染,Container component负责数据的获取和事件的响应。

遵循的设计原则:
  1. 单一职责原则: Presentational component负责ui,Container component负责数据和行为。
  2. Don't repeat yourself: Presentational component是纯ui组件,不包含业务逻辑,通常可以被复用。
示例
importReactfrom"react";
// Presentational componentexportdefaultfunctionImageList({ images, onClick }) {
returnimages.map((img, i) =><imgsrc={img} key={i} onClick={onClick} />);
}
// Container componentexportdefaultclassImageListContainerextendsReact.Component {
constructor() {
super();
this.state= {
images: []
    };
  }
componentDidMount() {
fetch("https://images.com")
      .then(res=>res.json())
      .then(({ images }) =>this.setState({ images }));
  }
handleClick() {
// ...  }
render() {
return<ImageListimages={this.state.images} onClick={handleClick} />;
  }
}

HOC

Higher-order component 是一个以组件为参数,返回一个新组件的函数,用于复用组件的逻辑,Redux的 connect 和 Relay的createFragmentContainer都有使用HOC模式。

遵循的设计原则:
  1. Don't repeat yourself:把可复用的逻辑放到HOC中,实现代码复用。
  2. Composition over inheritance: hoc中传入的组件和返回的组件是组合的关系, 也可以把多个HOC进行多次的嵌套组合。
示例
importReactfrom"react";
exportdefaultfunctionwithLoader(Component, url) {
returnclassHOCextendsReact.Component {
constructor(props) {
super(props);
this.state= {
loading: true,
data: {},
      };
    }
componentDidMount() {
fetch(url)
        .then((res) =>res.json())
        .then(({ data }) =>this.setState({ data }))
        .finally(() =>this.setState({loading: false}))
    }
render() {
if (this.state.loading) {
return<div>Loading...</div>;
      }
return<Component {...this.props} data={this.state.data} />;
    }
  };
}

Render prop

Render prop是指组件的使用者通过组件暴露的函数属性来参与定制渲染相关的逻辑。使用Render prop模式的库包括: React Router, Downshift and Formik.

遵循的设计原则:
  1. Don't repeat yourself:把可复用的逻辑放到组件中,实现代码复用。
  2. 依赖反转原则:通过render prop注入渲染相关的实现。
  3. 开闭原则(Open-closed principle): 通过render prop暴露扩展点,而不是直接定制组件。
示例
importReactfrom"react";
classLoaderextendsReact.Component {
constructor(props) {
super(props);
this.state= {
loading: true,
data: {},
    };
  }
componentDidMount() {
fetch(url)
      .then((res) =>res.json())
      .then(({ data }) =>this.setState({ data }))
      .finally(() =>this.setState({ loading: false }));
  }
render() {
if (this.state.loading) {
return<div>Loading...</div>;
    }
returnthis.props.renderData(this.state.data);
  }
}

Compound components

Compound components是指通过多个组件的组合来完成特定任务,这些组件通过共享的状态、逻辑进行关联。典型的例子是Select和Select.Option组件。使用Compound components模式的库包括:semantic ui;

遵循的设计原则:
  1. 单一职责原则(Single-responsibility responsibility): 拆分成多个组件,每个组件承担自己的职责。
  2. 开闭原则(Open-closed principle): 需要迭代增强功能时,可以通过创建新的子组件的方式进行扩展。
示例
importReactfrom"react";
constSelectContext=React.createContext({});
exportfunctionSelect({ value, onChange, children }) {
const [open, setOpen] =React.useState(false);
const [val, setValue] =React.useState(value);
return (
<divclassName={`select`}><divclassName="select-value"onClick={() => {
setOpen(true);
        }}
>        {val}
</div><SelectContext.Providervalue={{
value: val,
setOpen,
setValue: (newValue) => {
setValue(newValue);
if (value!==newValue) {
onChange(newValue);
            }
          },
        }}
>        {open&&children}
</SelectContext.Provider></div>  );
}
functionOption({ children, value }) {
const {
setOpen,
setValue,
value: selectedValue,
  } =React.useContext(SelectContext);
return (
<divclassName={`select-option ${value===selectedValue?"selected" : ""}`}
onClick={() => {
setValue(value);
setOpen(false);
      }}
>      {children}
</div>  );
}
functionOptionGroup({ children, label }) {
return (
<divclassName="select-option-group"><divclassName="select-option-group-label">{label}</div>      {children}
</div>  );
}
Select.Option=Option;
Select.OptionGroup=OptionGroup;
functionDemo() {
const [city, setCity] =React.useState("北京市");
return (
<Selectvalue={city} onChange={setCity}><Select.Optionvalue="北京市">北京市</Select.Option><Select.OptionGrouplabel="河北省"><Select.Optionvalue="石家庄市">石家庄市</Select.Option><Select.Optionvalue="保定市">保定市</Select.Option></Select.OptionGroup></Select>  );
}

Custom hooks

自定义hooks可以做到把与state和生命周期关联的可复用逻辑封装到独立的函数中, 上面的提及的一些模式都是基于组件的方案,自定义hooks是更细粒度的解决方案。

遵循的设计原则:
  1. Don't repeat yourself:把可复用的逻辑放到自定义hooks中,实现代码复用。
  2. 单一职责原则:每个自定义hooks是都是一个独立的逻辑单元。
示例:
import { useState, useEffect } from"react";
functionuseLoader(url) {
const [data, setData] =useState({});
const [loading, setLoading] =useState(false);
useEffect(() => {
setLoading(true);
fetch(url)
      .then((res) =>res.json())
      .then(({ data }) => {
setData({ data });
      })
      .finally(() =>setLoading(false));
  }, [url]);
return { data, loading };
}

结尾

上面提及的曾经在社区流行的设计模式,往往遵守了一些设计原则,从而能帮助开发者写出健壮,易维护的代码。但是我们需要能根据实际的场景做出判断,是否需要引入这些模式,毕竟还有一个设计原则是YAGNI (You aren't gonna need it)。

目录
相关文章
|
2月前
|
设计模式 消息中间件 算法
现货期权交易所开发模块化设计模式
现货期权交易所模块化设计通过解耦核心系统,构建契约化接口与清晰边界,提升迭代效率与容错能力。涵盖行情、撮合、风控等模块,支持独立部署、灰度发布与跨团队协同,降低开发成本,增强可扩展性与可观测性,助力高并发场景下的稳定运行与快速响应。
|
7月前
|
运维 前端开发 数据可视化
【CodeBuddy】挑战一句话开发一个完整项目之:React表单验证系统
本文分享了一个基于React 19构建的用户注册表单系统,采用模块化CSS和状态驱动视图更新,实现实时校验、错误提示与提交反馈等功能。核心亮点包括验证规则引擎(如密码复杂度校验)、交互反馈体系(输入框警示、按钮禁用)及加载动画优化。通过函数式更新确保状态同步,正则表达式实现多条件验证,CSS伪元素打造流畅体验。代码结构清晰,可扩展性强,适合作为React表单开发模板。文末附CodeBuddy免费下载链接,助力高效开发!
207 1
【CodeBuddy】挑战一句话开发一个完整项目之:React表单验证系统
|
前端开发 JavaScript API
React开发需要了解的10个库
本文首发于微信公众号“前端徐徐”,介绍了React及其常用库。React是由Meta开发的JavaScript库,用于构建动态用户界面,广泛应用于Facebook、Instagram等知名网站。文章详细讲解了Axios、Formik、React Helmet、React-Redux、React Router DOM、Dotenv、ESLint、Storybook、Framer Motion和React Bootstrap等库的使用方法和应用场景,帮助开发者提升开发效率和代码质量。
468 4
React开发需要了解的10个库
|
设计模式 算法 搜索推荐
后端开发中的设计模式应用与实践
在软件开发的广袤天地中,后端技术如同构筑高楼大厦的钢筋水泥,支撑起整个应用程序的骨架。本文旨在通过深入浅出的方式,探讨后端开发领域内不可或缺的设计模式,这些模式犹如精雕细琢的工具箱,能够助力开发者打造出既健壮又灵活的系统架构。从单例模式到工厂模式,从观察者模式到策略模式,每一种设计模式都蕴含着深刻的哲理与实践价值,它们不仅仅是代码的组织方式,更是解决复杂问题的智慧结晶。
|
设计模式 算法 搜索推荐
后端开发中的设计模式应用
在软件开发的浩瀚海洋中,设计模式犹如一座座灯塔,为后端开发者指引方向。本文将深入探讨后端开发中常见的设计模式,并通过实例展示如何在实际项目中巧妙应用这些模式,以提升代码的可维护性、扩展性和复用性。通过阅读本文,您将能够更加自信地应对复杂后端系统的设计与实现挑战。
238 3
|
10月前
|
设计模式 架构师 Java
设计模式觉醒系列(01)设计模式的基石 | 六大原则的核心是什么?
本文介绍了设计模式的六大原则,包括单一职责原则(SRP)、开闭原则(OCP)、里氏替换原则(LSP)、接口隔离原则(ISP)、依赖倒置原则(DIP)和迪米特法则。通过具体案例分析了每个原则的应用场景及优势,强调了这些原则在提升代码可维护性、可复用性、可扩展性和降低耦合度方面的重要作用。文章指出,设计模式的核心在于确保系统模块间的低耦合高内聚,并为后续深入探讨23个经典设计模式打下基础。
|
12月前
|
设计模式 Java 程序员
【23种设计模式·全精解析 | 概述篇】设计模式概述、UML图、软件设计原则
本系列文章聚焦于面向对象软件设计中的设计模式,旨在帮助开发人员掌握23种经典设计模式及其应用。内容分为三大部分:第一部分介绍设计模式的概念、UML图和软件设计原则;第二部分详细讲解创建型、结构型和行为型模式,并配以代码示例;第三部分通过自定义Spring的IOC功能综合案例,展示如何将常用设计模式应用于实际项目中。通过学习这些内容,读者可以提升编程能力,提高代码的可维护性和复用性。
2597 1
【23种设计模式·全精解析 | 概述篇】设计模式概述、UML图、软件设计原则
|
前端开发 JavaScript 开发者
React 组件化开发最佳实践
【10月更文挑战第4天】React 组件化开发最佳实践
397 4
|
XML 移动开发 前端开发
使用duxapp开发 React Native App 事半功倍
对于Taro的壳子,或者原生React Native,都会存在 `android` `ios`这两个文件夹,而在duxapp中,这些文件夹的内容是自动生成的,那么对于需要在这些文件夹中修改的配置内容,例如包名、版本号、新架构开关等,都通过配置文件的方式配置了,而不需要需修改具体的文件
|
设计模式 JavaScript Java
后端开发中的设计模式应用
本文将深入探讨后端开发中常见的设计模式,包括单例模式、工厂模式和观察者模式。每种模式不仅会介绍其定义和结构,还会结合实际案例展示如何在后端开发中应用这些模式来优化代码的可维护性与扩展性。通过对比传统方法与设计模式的应用,读者可以更清晰地理解设计模式的优势,并学会在项目中灵活运用这些模式解决实际问题。

热门文章

最新文章