首页 web前端 js教程 模块化 React 架构

模块化 React 架构

Nov 09, 2024 pm 07:29 PM

Modular React architecture

浅谈模块化架构

什么是模块化架构?让我们通过一个例子来了解它不是什么,并且
我们将努力改变它。到最后你可能会相信它
优点或这是对时间的巨大浪费。

这是我在工作中经历的一个成长心态的真实场景。姓名和详细信息
虽然是匿名的,但一个常见概念的现实世界示例应该很有趣
如果没有别的的话,通过。

要求以及如何找到它们

我们的网站有一个位于网站标题中的按钮。它显示有多少
用户已经离开了 V-Bucks,但也融入了一些业务逻辑:

  • 如果这是他们第一次访问该网站,请打开一个弹出窗口来欢迎他们 并展示他们可以用 V-Bucks 做些什么
  • 如果他们有
  • 如果他们是基本用户,则显示一种样式的按钮;如果是 SuperDuper 用户,则显示 另一个更漂亮的按钮

等等。我们的产品经理和项目经理这样的例子还有很多
设计经理和 V-Bucks 集团董事梦想着我们需要
手柄。

实习生 Jimbo 的任务是实现这个,因为这只是一个
按钮!

他筛选了 Figma 设计的 15 种相互冲突的迭代。他发现
有多少个 PM,就在多少个单独的 Word 文档中包含这些要求。他组织并
与七个团队一起进行七次知识转移会议,以揭开
古老的专有知识知道哪些服务将提供他所需的数据
用于用户类型和 V-Bucks 数量。内容团队向他保证
所有字符串的最终版本将在年底获得法律和营销部门的批准
一周,这样,他就准备好构建这个按钮了。

黑客方法

这是他的 V-Bucks 按钮、弹出窗口和相关内容的第一次迭代
业务逻辑。

Jimbo 对他提出的简单目录结构感到满意:

/v-bucks-button
├── button.tsx
├── index.ts
└── /v-bucks-popover
│ ├── popover.tsx
登录后复制
登录后复制
登录后复制

所以他开始构建这个按钮,而且一开始很天真。

export const VBucksButton: React.FC<VBBProps> = ({ ... }) => {
  // Set up state
  const authConfig    = { ... }
  const { user }      = useAuth({ ...authConfig })
  const { vBucks }    = useGetVBucks({ user })
  const { telemetry } = useTelemetry()
  const { t }         = useTranslation('vBucksButton.content')
  const styles        = useButtonStyles()

  // Derive some state via business logic
  const handleClick = () => { ... }
  const buttonText  = vBucks === ERROR ? '--' : vBucks.toString();
  // About 25 more lines of various button state, error handling,
  // conditional rendering, with comments throughout explaining
  // why we're showing or hiding something or other

  const popoverProps = {
    // About 200 lines of typical popover handling,
    // telemetry, business logic, content to display, etc
  }

  const tooltipProps = {
    // Another 100 lines of the same for tooltip
  }

  return (
    <VBucksPopover
      {...popoverProps}
      trigger={
        <Tooltip {...tooltipProps}>
          <button
            ariaLabel={t('ariaLabel')}
            className={`
              about seven-hundred classnames for responsive design,
              accessibility, conditional premium styles, et cetera`}
            onClick={handleClick}>
            {buttonText}
          </button>
        </Tooltip>
      }
    />
  )
}
登录后复制
登录后复制

他已经实现了第一次尝试。 VBucksPopover 也有类似的复杂
业务逻辑、错误处理、状态管理、样式和注释
以运输名义的技术债务。

这个按钮只有不到 400 行,非常简单。即使弹出窗口是
另外500行意大利面条。真的是“清理”还是分裂
以任何方式使我们或我们的用户受益?这取决于。如果这就是我们所需要的
这个按钮,谁在乎呢。让我们继续前进吧!

但是两个月过去了,另一个产品团队的PM和设计师爱上了
您的按钮并希望将其放在应用程序的标题中。他们有一个简单列表,没有
来自他们的压力,他们希望你适应一些改变,如果
您可以在当天结束前给出 LT 的预计到达时间,那就太好了,谢谢:

  • 更新按钮的样式并根据其显示的应用程序显示文本
  • 每个应用程序显示一组完全不同的弹出窗口
  • 当用户用完 V-Bucks 时,打开一个新的全公司范围内的标准追加销售模式, 但仅限于某些地区,并且仅限 16 岁的用户,并且仅限于 实验A组

Jimbo 能否将所有这些新功能塞进同一个组件中?

是的。拆分或重构会给用户带来好处还是给你的经理留下深刻印象?

不。但是在这种复杂程度上,重构有一些强有力的论据:

  • 开发理智
  • 当 Jimbo 因不重构而被 PIP 时取代他的开发人员的理智
  • 更多次数,让你下次从一开始就做得更好
  • 稍后写博客的内容

模块化架构方法

清洁守则倡导者和其他了解足够知识的肛门类型的道德
定期在 Stack Overflow 上回答,甚至你的祖父母也会看一些东西
像这样:

  • KISS、DRY 和其他缩写毯子
  • 关注点分离
  • 原子性!脱钩!拟声词!

这些都很棒,有助于为 Jimbo 的下一次尝试提供信息。
之后他就没有被画中画了 所有,而且实际上还得到了提前交付和分享的促销
这么多的会议和文件。

但他现在更聪明了,学会了一种很酷的方法来实践这些格言。看起来
像这样的东西:

/v-bucks-button
├── button.tsx
├── index.ts
└── /v-bucks-popover
│ ├── popover.tsx
登录后复制
登录后复制
登录后复制

看起来像大量按钮和弹出框的样板。为什么会这样
更好吗?

这取决于。以下是 Jimbo 的简要概述及其基本原理:

  • 将每个组件拆分为容器和渲染器
  • 将状态和业务逻辑移入钩子
  • 容器使用钩子并将任何道具传递给渲染器
  • 渲染器只关心渲染它所提供的内容
  • 通用功能、业务逻辑或常量可以存在于 utils 中
  • 不同类型的单独文件;它们往往被导入到多个文件中并且 成为你无论如何都需要提取的循环依赖
  • 提取的 TailwindCSS - 下面有更多内容

无限可扩展!这些构建块不会被
分解 任意规则,例如代码行或“复杂性”。它们被分解为
目的:每个概念边界都有一个目的。

PM 要你制作 10 个新的爆米花?没问题——Jimbo 的架构可以
处理一下。

领导层希望在某些应用程序中获得更好的销售指标,但其他团队则不然
有资金建立遥测技术来支持这一点。伟大的!我们有
我们可以水平扩展以满足各种变化的遥测实用程序
要求。

彻底的重新设计意味着每个弹出窗口都需要显示不同的内容,
根据不同的条件。现在,通常要简单得多,因为所有
我们渲染的东西,以及我们用来渲染它的所有逻辑,都存在于明确定义的
中 块。它们不再混杂在一大堆冲突和逻辑中
链长 20 行。

这是此容器/渲染器模式的示例:

/v-bucks-button
├── button.tsx
├── index.ts
└── /v-bucks-popover
│ ├── popover.tsx
登录后复制
登录后复制
登录后复制
export const VBucksButton: React.FC<VBBProps> = ({ ... }) => {
  // Set up state
  const authConfig    = { ... }
  const { user }      = useAuth({ ...authConfig })
  const { vBucks }    = useGetVBucks({ user })
  const { telemetry } = useTelemetry()
  const { t }         = useTranslation('vBucksButton.content')
  const styles        = useButtonStyles()

  // Derive some state via business logic
  const handleClick = () => { ... }
  const buttonText  = vBucks === ERROR ? '--' : vBucks.toString();
  // About 25 more lines of various button state, error handling,
  // conditional rendering, with comments throughout explaining
  // why we're showing or hiding something or other

  const popoverProps = {
    // About 200 lines of typical popover handling,
    // telemetry, business logic, content to display, etc
  }

  const tooltipProps = {
    // Another 100 lines of the same for tooltip
  }

  return (
    <VBucksPopover
      {...popoverProps}
      trigger={
        <Tooltip {...tooltipProps}>
          <button
            ariaLabel={t('ariaLabel')}
            className={`
              about seven-hundred classnames for responsive design,
              accessibility, conditional premium styles, et cetera`}
            onClick={handleClick}>
            {buttonText}
          </button>
        </Tooltip>
      }
    />
  )
}
登录后复制
登录后复制
/vBucksButton
├── /hooks
│ ├── index.ts
│ └── useButtonState.hook.ts
├── /vBucksPopover
│ ├── /app1Popover
│ │ ├── /hooks
│ │ │ ├── index.ts
│ │ │ └── usePopoverState.hook.ts
│ │ ├── ...
│ ├── /app2Popover
│ ├── index.ts
│ ├── popover.renderer.tsx
│ ├── popover.styles.ts
│ ├── popover.tsx
│ └── popover.types.ts
├── /utils
│ ├── experimentation.util.ts
│ ├── store.util.ts
│ ├── telemetry.util.ts
│ └── vBucks.businessLogic.util.ts
├── button.renderer.tsx
├── button.styles.ts
├── button.tsx
├── button.types.ts
└── index.ts
登录后复制

旁白:TailwindCSS 文档明确建议不要使用 @apply 来提取这样的公共类。这导致包大小几乎为零差异,除了“你必须想出类名”之外没有其他差异。生产级 CSS 几乎总是有几十行那么长,乘以给定组件中需要样式化的元素数量。这种权衡在 90% 的情况下似乎都是值得的。

其余现有的和新的业务逻辑位于钩子和实用程序中!

这种新架构满足了狂热者的需求,并使事情更容易扩展或
删除或移动。

编写单元测试变得不那么痛苦,因为你已经有了明确的定义
边界。您的渲染器不再需要模拟十种不同的服务来
验证它是否在给定一些输入的情况下显示了一组闪光。你的钩子可以
单独测试它们是否符合您预期的业务逻辑。

你的整个状态层刚刚改变了吗?如果您的
中的代码那就太可惜了 钩子与使用它的代码紧密耦合,但现在它更简单
更改,您的渲染器仍然只是等待一些输入。

最后的想法

这种模块化架构添加了大量样板,最终可以提供
零利益。

如果您正在从事一个充满激情的项目或
,我实际上无法推荐它 优先考虑运输和提供价值。如果你有
的东西 似乎它的范围可能会随着时间的推移而扩大,或者您可能想要
在 POC 后进行彻底检修,有时可以减少技术债务。

您可以使用 Plop 等工具来生成此样板。

那么我从 Jimbo 的工作和模块化架构中真正学到了什么?

我们在学校和世界各地的 Well Ackshuallys 中学习的干净代码和缩写词
是一系列的一端。将功能性意大利面条代码组合在一起是另一回事
结束,并且通常效果很好,因为最终所有代码都是技术债。

最佳解决方案存在于某种量子态或这些末端的组合中,并且
我们选择的路径可能取决于:

  • 我们有多关心我们正在构建的东西
  • 管理层要求更新和预计到达时间的频率
  • 读到这样的东西,一种方法恰好出现在你的 当你构建下一个东西时的意识
  • 沮丧、痛苦
  • 意大利面变成了性能瓶颈,你不得不重写它
  • 样板文件变得如此枯燥,以至于你不得不偷工减料

以上是模块化 React 架构的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1659
14
CakePHP 教程
1416
52
Laravel 教程
1310
25
PHP教程
1258
29
C# 教程
1232
24
神秘的JavaScript:它的作用以及为什么重要 神秘的JavaScript:它的作用以及为什么重要 Apr 09, 2025 am 12:07 AM

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

JavaScript的演变:当前的趋势和未来前景 JavaScript的演变:当前的趋势和未来前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

JavaScript引擎:比较实施 JavaScript引擎:比较实施 Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

JavaScript:探索网络语言的多功能性 JavaScript:探索网络语言的多功能性 Apr 11, 2025 am 12:01 AM

JavaScript是现代Web开发的核心语言,因其多样性和灵活性而广泛应用。1)前端开发:通过DOM操作和现代框架(如React、Vue.js、Angular)构建动态网页和单页面应用。2)服务器端开发:Node.js利用非阻塞I/O模型处理高并发和实时应用。3)移动和桌面应用开发:通过ReactNative和Electron实现跨平台开发,提高开发效率。

Python vs. JavaScript:学习曲线和易用性 Python vs. JavaScript:学习曲线和易用性 Apr 16, 2025 am 12:12 AM

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

如何使用Next.js(前端集成)构建多租户SaaS应用程序 如何使用Next.js(前端集成)构建多租户SaaS应用程序 Apr 11, 2025 am 08:22 AM

本文展示了与许可证确保的后端的前端集成,并使用Next.js构建功能性Edtech SaaS应用程序。 前端获取用户权限以控制UI的可见性并确保API要求遵守角色库

从C/C到JavaScript:所有工作方式 从C/C到JavaScript:所有工作方式 Apr 14, 2025 am 12:05 AM

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。

使用Next.js(后端集成)构建多租户SaaS应用程序 使用Next.js(后端集成)构建多租户SaaS应用程序 Apr 11, 2025 am 08:23 AM

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务

See all articles