关于前端:编写高质量可维护的代码组件的抽象与粒度

27次阅读

共计 4930 个字符,预计需要花费 13 分钟才能阅读完成。

这是第 79 篇不掺水的原创,想获取更多原创好文,请搜寻公众号关注咱们吧~ 本文首发于政采云前端博客:编写高质量可保护的代码:组件的形象与粒度

前言

作为一名粗劣的前端猪猪女孩,也有那么点想让本人的代码同样看起来粗劣一点。所以在拿到新需要的 UI 设计稿时,常常会面临如下问题:如何拆解页面?如何划分组件才算是正当?如同用于组件拆分的 A 计划和 B 计划在以后业务场景下也都还算正当,那到底要怎么抉择?组件的形象与粒度貌似是一个陈词滥调的问题了~学习了很多前辈的文章,那么明天联合业务场景,也来讲下我的心得~

什么是组件

React 官网文档上说:组件,从概念上相似于 JavaScript 函数。它承受任意的入参(即“props”),并返回用于形容页面展现内容的 React 元素。

Vue 官网文档说:组件是可复用的 Vue 实例,且带有一个名字。咱们能够在一个通过 new Vue 创立的 Vue 根实例中,把这个组件作为自定义元素来应用。

其实总的来说,无论什么语言框架,组件就是一段代码片段,它能够实现某些指定的性能或渲染特定的展现成果,咱们个别能够通过 import 的形式将其引入到我的项目代码中。本文接下来将以 React 为例进行相干形容。

组件的形象

组件形象的过程就是将通用性代码“提取”或是“抽取”进来的过程,那么问题来了,咱们为什么要抽组件呢?

为什么要抽组件

说到为什么要抽取组件,不晓得各位读者有没有遇到过一个 js 文件中有 1k+ ~ 2k+ 行 React 代码,甚至更多行代码的状况。这种状况往往导致代码难以保护,当有新的需要波及相干改变时,在肯定水平上减少了代码的学习老本(特地是当你刚刚新接手了一份齐全不相熟的我的项目的时候)。

其次,某些状况下,有一部分代码在不同场景下其实是能够复用的,例如新增和编辑的弹窗,可能只有弹窗的题目和某些字段有局部差别,此时没必要把高度类似的代码复制两遍,减少代码的冗余。

因而,在咱们日常开发中,组件抽取是有必要的,其目标在于代码的 分层 复用,升高我的项目的复杂度。

组件形象的根本准则

单一性

单一性要求一个组件具备高内聚,低耦合的特色,它只负责一件事件,不要耦合一些没必要的逻辑,并且尽量不要和其余组件有过于多的双向交互和相互依赖关系。单一性并不代表着不能够援用其余组件,以后组件可能是外层的容器组件,外面蕴含一些子组件,这样的设计是没问题的。

复用性 / 通用性

在设计组件的时候,肯定要思考组件的复用性或者说是通用性。这是指,当组件封装好后,能够在 相似 的应用场景中间接调用。这要求咱们在设计组件的时候,思考组件性能的通用性,以及思考组件入参的合理性。

此时有两种状况:

一种是很多不同的我的项目间,可能存在相似的应用场景,因而会提炼出一个公共的组件,为了复用。个别咱们称之为根底组件或业务组件,权且叫它公共组件吧。

另一种是在我的项目外部,仅在以后场景下作为一个独立的模块能够抽取进去作为一个组件,临时称之为我的项目组件。

公共组件和我的项目组件在设计上的偏重也有所不同,公共组件要更多的思考通用性,通过一个组件满足不同我的项目中类似的应用场景,比方 AntD 根底组件库。而我的项目组件更多的是解决以后业务中的非凡场景,可能是页面拆解后的不同模块,也可能是不同操作的弹窗,往往这种组件不适宜间接“移植”到其余我的项目中应用。

然鹅,对于一个组件来说,集体认为也不能一味的谋求通用性使其变得难以保护。例如,当遇到下述页面的时候,要如何形象组件呢?

不难发现,页面中交易方式、根底配置和合同设置这三个模块其实是具备肯定共性的,全副出现为列表模式,只是在某些列上有展现差别。前辈的做法是,思考了所有状况,形象成一个组件。通过 title 辨别模块名称,因为仅在交易方式模块有操作列,因而通过 areaCode 辨别以后页面下的不同模块等。

<TableConfiguration
  // 基本参数
  title="根底配置" // 题目名称
  data={baseSettingData} // 展现数据
  areaCode="baseSettingConfig" // 模块 code
  config={baseSettingConfig} // 一些业务逻辑参数
  // 新增参数
  pageId={this.pageId} // 以后页面 Id
  userIdentity={userIdentity} // 用户身份
/>

在业务倒退后期,这样抽取的组件确实应用起来很不便,且通用性很强。但随着业务的收缩,同一我的项目中不同页面开始呈现相相似的模块,于是新增 pageId 标识,用于辨别不同的页面以及对应页面的非凡逻辑。又过了一段时间,新增 userIdentity 标识,用于管制不同登录用户对页面的查看或操作权限。

长此以往,新增的参数越来越多,组件外部开始呈现大量的判断逻辑,只管这个组件通用性很好,能应答各种页面展现逻辑,但这也使它自身变得逐步难以保护。还有一种比拟好的解决方案是通过表单核心生成一份这样的页面,可参考动态化表单设计。

拆散解决

师父曾教诲我说抽组件最好做一下业务层和视图层的拆散解决,其中视图层次要负责页面展现款式和交互,业务层次要负责解决业务逻辑,比方接口调用,数据结构调整等。这样做的益处除了职责拆散,还能够无效进步组件性能(比方视图层能够用 PureComponent 解决)。

另外,例如上述的新增和编辑弹窗,当新增和编辑两个操作须要别离调用不同接口时,业务层和视图层的拆散解决能够防止组件中耦合对“新增”或“编辑”的判断,它们能够共用一个视图,并在各自的业务层实现不同的业务逻辑。

组件分类

业务组件 vs UI 组件

业务组件侧重于数据和业务的逻辑解决,其中数据个别通过接口获取。目前本团队保护的业务组件库,能够使开发人员即来即用,组件外部有欠缺的性能和接口数据处理,将组件引入到我的项目后可间接实现对应性能。

UI 组件个别也能够称为根底组件,它们常常在多个中央被复用,且不耦合任何的业务性能,例如:AntD 组件库。UI 组件侧重于页面展现成果,大部分 UI 组件具备原子性,一些简单的 UI 组件能够由根本的 UI 组件形成。个别状况下组件外部的数据来源于父组件传递过去的 props。

纯组件 vs 非纯组件

有一天,我看到前辈大神这么写的代码

export default class NotFound extends PureComponent {// 此处省略具体代码}

于是去学习了下纯组件和非纯组件的区别,首先让咱们理解下 React 中的各种组件一文中对 React 组件从新渲染机制的形容:

个别当一个组件的 props(属性)或者 state(状态)产生扭转的时候,也就是父组件传递进来的 props 发生变化或者应用 this.setState 函数时,组件都会进行从新渲染。

而在承受到新的 props 或者 state 到组件更新之间,其实会执行生命周期中的一个办法 shouldComponentUpdate,当该办法返回 true 时才会进行重渲染,如果返回 false 则不会进行重渲染。

纯组件和非纯组件的区别在于,个别状况下非纯组件并未主动实现 shouldComponentUpdate 办法的性能(但能够手动调用这个钩子),而纯组件中利用 shallowEqual 的办法对 props 和 state 做浅比拟实现了该性能。理论利用中,纯组件个别用于纯展现型组件,绝对于非纯组件来说,缩小了手动判断 props 或者 state 变动的繁琐操作。并且,纯组件能够通过缩小 render 调用次数来升高性能损耗,然而应用过程中也肯定要确保此类组件的渲染仅取决于 props 与 state。

非纯组件的话,其实咱们日常开发中比拟罕用。个别状况下,在不做非凡解决时,失常 extends Component 进去的组件都能够认为是非纯组件。

export default class MyComponent extends Component {}

咱们能够依据理论的开发场景抉择继承自 PureComponent 还是 Component。值得注意的是,因为纯组件中做的是浅比拟,因而带有深层嵌套的数据是比照不进去的,请慎用~

组件的粒度

提到组件的粒度,大多数人的第一反馈可能认为拆分的越细越好。然而,这样肯定是最优解嘛?集体认为其实不是的。

组件拆解的过于粗疏可能导致某些参数从父组件开始一层层向子组件传递,容易漏传,错传,或者其中某层组件遗记判空的时候,可能会导致页面报错。尽管能够通过 React Context 去获取,不过如同还是“徒手传递”的人更多一点。但组件如果拆解的太粗略往往也会导致复用率低、难以保护等问题。

讲到这里,让我想到了原子设计。原子设计是 Brad Forst 于 2013 年提出的设计概念,该作者用 5 个层级来形容组件库的设计。做下类比,映射到开发人员应用和熟知的组件中,集体认为也适宜形容组件粒度。

  • 原子组件

如果说,原子是物质的根本组成部分,那么原子组件就能够作为形成咱们所有页面的最根本组成部分。原子组件,能够为上文中提到的根底 UI 组件,例如一个 Input 或一个 Button。它们往往具备不可再拆分的个性,是其余组件的根底。

  • 分子组件

分子组件个别由几个简略的原子组件组成,比方由一个 Label 和一个 Input 组成的姓名输出组件。这种粒度的组件初步具备肯定状态和本身属性,与原子组件相比,有肯定的可操作性。

  • 生物组件

生物组件是由原子组件及分子组件组成的绝对简单的形成物,它是一种作为一个单元发挥作用的集合体。比方由姓名输出组件和一组按钮组成的搜寻组件。在这个组件中,姓名输出组件被搁置在一种应用环境中,实现了简略的性能。

有些生物组件是由不同的分子组件形成,但也有可能由雷同的分子组件形成,比方网站首页的商品展现组件,该组件由六宫格组成,每个格子应用同一个分子组件进行渲染和展现。

  • 模板组件

模板组件是由原子、分子、生物组件依照肯定布局构造组成的区块。它们专一于页面的根底内容构造,而不是页面的最终内容。模板组件是更简单一点的生物组件,更多的赋能于性能和展现。

  • 页面

最终,通过不同模板组件的拼装,能够生成一个残缺的页面。

在理论利用中,组件设计时的粒度往往也须要根据具体的场景具体分析,但准则能够参考高内聚,低耦合的思路,使本人的组件易于保护,同时使本人的整个我的项目代码看起来干净利落。

总结

其实,自己真心认为组件的形象与形象粒度这件事,没有一个变化无穷的统一标准,也没有对与错。在根本准则不变的状况下,更多的应该去关注如何适配不同的业务场景和需要要求,求的是“适宜”。有时,同样的场景,组件粒度的规范也会随业务场景变动而变动,甚至可能随场景而继续重构。不过为了代码更好的保护和分层,以及防止代码逻辑的适度叠加和收缩,团队中能够制订一些组件形象的标准稍稍加以束缚。

参考文献

React 组件设计实际总结 02 – 组件的组织

React 中的各种组件

React PureComponent 使用指南

组件化设计:原子设计实际

招贤纳士

政采云前端团队(ZooTeam),一个年老富裕激情和创造力的前端团队,隶属于政采云产品研发部,Base 在风景如画的杭州。团队现有 40 余个前端小伙伴,平均年龄 27 岁,近 3 成是全栈工程师,妥妥的青年风暴团。成员形成既有来自于阿里、网易的“老”兵,也有浙大、中科大、杭电等校的应届新人。团队在日常的业务对接之外,还在物料体系、工程平台、搭建平台、性能体验、云端利用、数据分析及可视化等方向进行技术摸索和实战,推动并落地了一系列的外部技术产品,继续摸索前端技术体系的新边界。

如果你想扭转始终被事折腾,心愿开始能折腾事;如果你想扭转始终被告诫须要多些想法,却无从破局;如果你想扭转你有能力去做成那个后果,却不须要你;如果你想扭转你想做成的事须要一个团队去撑持,但没你带人的地位;如果你想扭转既定的节奏,将会是“5 年工作工夫 3 年工作教训”;如果你想扭转原本悟性不错,但总是有那一层窗户纸的含糊… 如果你置信置信的力量,置信平凡人能成就不凡事,置信能遇到更好的本人。如果你心愿参加到随着业务腾飞的过程,亲手推动一个有着深刻的业务了解、欠缺的技术体系、技术发明价值、影响力外溢的前端团队的成长历程,我感觉咱们该聊聊。任何工夫,等着你写点什么,发给 ZooTeam@cai-inc.com

正文完
 0