首页 > 其他分享 >如何编写难以维护的 React 代码?耦合通用组件与业务逻辑

如何编写难以维护的 React 代码?耦合通用组件与业务逻辑

时间:2023-10-10 12:33:50浏览次数:60  
标签:function content return title React 耦合 组件 isMobile

在众多项目中,React代码的维护经常变得棘手。其中一个常见问题是:将业务逻辑直接嵌入通用组件中,导致通用组件与业务逻辑紧密耦合,使其失去“通用性”。这种做法使通用组件过于依赖具体业务逻辑,导致代码难以维护和扩展。

示例:屎山是如何逐步堆积的

让我们看一个例子:我们在业务组件 PageA 和 PageB 中都使用了通用组件 Card。

function PageA() {
  return (
    <>
      {/* ... */}
      {listA.map(({ title, content }) => <Card title={title} content={content} />)}
    </>
  )
}

function PageB() {
  return (
    <>
      {/* ... */}
      {listB.map(({ title, content }) => <Card title={title} content={content} />)}
    </>
  )
}

function Card({ title, content }) {
  return (
    <div>
      <Title>{title}</Title>
      <Content>{content}</Content>
    </div>
  )
}

某一天,出现了一个新需求:在手机端的所有页面都需要显示 Footer。于是,代码被修改如下:

function PageA({ isMobile }) {
  return (
    <>
      {/* ... */}
      {listA.map(({ title, content }) => (
        <Card title={title} content={content} isMobile={isMobile} />
      ))}
    </>
  )
}

function PageB({ isMobile }) {
  return (
    <>
      {/* ... */}
      {listB.map(({ title, content }) => (
        <Card title={title} content={content} isMobile={isMobile} />
      ))}
    </>
  )
}

function Card({ title, content, isMobile }) {
  return (
    <div>
      <Title>{title}</Title>
      <Content>{content}</Content>
      {isMobile && <Footer />}
    </div>
  )
}

随后的某一天,小张接手了这个项目,又有新需求:只有第偶数个 Card 才应该显示 Footer。于是,秉承着最小影响范围的原则,代码被改成了这样:

function PageA({ isMobile }) {
  return (
    <>
      {/* ... */}
      {listA.map(({ title, content }, index) => (
        <Card title={title} content={content} isMobile={isMobile} index={index} />)
      )}
    </>
  )
}

function PageB({ isMobile }) {
  return (
    <>
      {/* ... */}
      {listB.map(({ title, content }, index) => (
        <Card title={title} content={content} isMobile={isMobile} index={index} />)
      )}
    </>
  )
}

function Card({ title, content, isMobile, index }) {
  return (
    <div>
      <Title>{title}</Title>
      <Content>{content}</Content>
      {isMobile && index % 2 === 1 && <Footer />}
    </div>
  )
}

随后的某一天,小王接手了这个项目,又有新需求。秉承着最小影响范围的原则 ......

分析原因

乍看之下,每次修改都是“局部最优”的,尽量修改最少的代码以限制影响范围,以确保在添加新功能时不引入错误。然而,实际上,由于每次“偷懒”,我们都违反了原则,导致代码变得越来越混乱。

原则

分离关注点原则(Separation of Concerns)是计算机科学和软件工程的基本设计原则之一,旨在帮助程序员更好地组织和管理复杂的系统。该原则的核心思想是将大型系统或程序分解为多个互相独立的组件,每个组件负责解决特定的关注点或任务,而不会受到其他关注点的干扰。这有助于提高代码的可维护性、可扩展性和可重用性。

开放-封闭原则(Open-Closed Principle,OCP):
这个原则表明软件实体(类、模块、函数等)应该对扩展开放,但对修改关闭。这意味着应该通过扩展现有的代码来引入新功能,而不是修改已有的代码。这有助于减少代码的风险,因为修改现有代码可能导致不可预测的副作用。

重构

将上述原则应用于这个示例中:通用组件应该只了解与自身相关的信息,Card 组件只关心何时显示 Footer,而不关心它在何处使用以及是否为第偶数个。让我们重构代码:

function PageA({ isMobile }) {
  return (
    <>
      {/* ... */}
      {listA.map(({ title, content }, index) => (
        <Card title={title} content={content} showFooter={isMobile && index % 2 === 1} />)
      )}
    </>
  )
}

function PageB({ isMobile }) {
  return (
    <>
      {/* ... */}
      {listB.map(({ title, content }, index) => (
        <Card title={title} content={content} showFooter={isMobile && index % 2 === 1} />)
      )}
    </>
  )
}

function Card({ title, content, showFooter }) {
  return (
    <div>
      <Title>{title}</Title>
      <Content>{content}</Content>
      {showFooter && <Footer />}
    </div>
  )
}

通过这次重构,我们成功解耦了通用组件和业务逻辑,使代码更易于维护和扩展。

标签:function,content,return,title,React,耦合,组件,isMobile
From: https://www.cnblogs.com/forzhaokang/p/17753943.html

相关文章

  • 界面组件DevExpress WinForms v23.2新功能预览 - 增强MVVM相关功能
    本文主要描述了DevExpressWinForms即将在几个月之后发布的v23.2中包含的新功能,持续关注我们获取更多最新资讯哦~DevExpressWinForms有180+组件和UI库,能为WindowsForms平台创建具有影响力的业务解决方案。同时能完美构建流畅、美观且易于使用的应用程序,无论是Office风格的界面,......
  • vue 基于 el-upload 封装视频上传组件
    新建video-upload.vue文件:<template> <divclass="video-upload-com">  <el-upload:action="uploadUrl":before-upload="beforeAvatarUpload":file-list="mediaList":on-success="handleSuccess":o......
  • uni-app清空父组件下拉框时清空子组件下拉框的值
    父组件:<template><view><view>这是登录界面<button@click="RedirdectToMain">跳转到首页</button></view></view><view><uni-file-pickerv-model=&quo......
  • Vue组件各个属性执行顺序问题
    转自:https://blog.csdn.net/m0_62763606/article/details/131694339       在制作波动短视频效果时,在data中定义了一个变量,默认值为null。后来该变量在mounted中被赋值,而后在watch侦听属性中使用立即侦听时使用了该变量却显示为null,后发现这关系到各个组件属性执行顺序问......
  • v-model 原理、v-model 应用于组件 实现组件通信
    原理:v-model本质上是一个语法糖。例如应用在输入框上,就是value属性和input事件的合写(如果应用于复选框,就是checked属性和change事件的合写,下拉菜单是value属性和change事件的合写)作用:提供数据的双向绑定     ①数据变,视图跟着变  :value   ......
  • 使用 Webpack 的 require.context 来获取组件
    代码constrequireComponent=require.context('@/views',//组件文件夹的相对路径true,//是否查找子文件夹/\.vue$///匹配组件文件的正则表达式)输出console.log(requireComponent.keys())原理require.context在生产环境中也能获......
  • 关键组件
    Tamagui提供各种本机和Web组件,例如按钮、开关、堆栈、输入、工作表等。然而,它提供的不仅仅是一个漂亮的组件库,它还有自己的编译器,可以扁平化您的组件树并修改您的样式以最适合您的应用程序运行的任何平台。可以在Expo和Next.js应用程序中使用,允许您在本机应用程序和Web......
  • 组件通信方案
    组件通信是指组件与组件之间的数据传递。组件的数据是独立的,无法直接访问其他组件的数据,想用其他组件的数据,需要通过组件通信方案。 组件关系分类:父子关系、非父子关系 组件通信方案:父子关系:props(父传子)和$emit(子传父)非父子关系:①provide&inject     ......
  • useState() and useEffect() in react
    foruseState(),see:https://www.freecodecamp.org/news/usestate-vs-redux-state-management/  foruseEffect(),see: https://www.freecodecamp.org/news/react-useeffect-absolute-beginners/简单说就是:当前component之行完毕后会之行useEffect定义的第一个参数的函......
  • 风控指南 | 风控引擎如何快速管理组件?
    风控组件是指在风险控制系统中用于监测、识别和处理各类风险行为的模块或工具。它们通过使用不同的算法、规则和技术,协助机构或企业实施有效的风险管理和防范措施。风控组件通过数据分析、模型建立、规则引擎等技术手段,帮助机构或企业及时识别和预警各类风险行为,并采取相应的措施......