基于React组件开发方法,提供了大量富前端web应用的技术实践。社区逐渐形成了稳定的组件规范。本文从API层面总结了6种组件类型,分析了它们的优势。缺点和适用场景,为日常组件开发提供方法指南。这六种类型是结构组件、样式组件、复合组件、配置组件、受控组件和非受控组件。结构组件和样式组件结构组件定义了组件的通用结构,该结构的具体实现对外传输。样式组件决定了组件的结构细节,只需要对外传递参数就可以渲染出预期的样式。样式化组件是更常用的组件类型。很少有开发者会根据一个设计稿来推断组件未来可能发生的变化,这也导致样式组件的复用性和可扩展性较弱。对于比较常见的组件,比如Button、Modal、Form等,不应该只提供样式实现,而是抽象结构组件。这两种类型不是非此即彼的关系。样式组件固定的API参数可以降低使用成本,结构组件灵活的API设置可以提供扩展性。结合两者的优点可以构建一个简单且可扩展的扩展组件。关于两者结合的优势最有说服力的实践是公共组件库。结构化组件可以显着降低业务方的沟通成本和访问风险。下面的示意图演示了业务端与组件库的两种通信模型:样式组件库与业务端的通信模型。结构组件库与业务端的通信模型。以上两种模式各为一个工时。样式类组件库完成一个需求变更需要三个工时,业务方还要等待组件库。功能实现后,就可以进行下一步了。结构化组件库赋予业务方更大的自主权,无需等待组件库实现新功能,通过自定义结构满足当前需求。组件库有足够的时间分析需求是否通用,是否值得提供新的API。结构组件在这个过程中起到了缓冲区的作用,使得业务方和组件库能够并行协同开发,保证各自的研发效率和节奏。复合组件和配置组件复合组件以JSX为主体,通过组件间嵌套组件来描述业务逻辑。配置组件通过props传递数据结构,组件根据预设逻辑渲染视图。日常开发倾向于编写配置组件,复合组件在通用组件库中出现较多。复合组件结构清晰,可扩展性高。组件用户可以通过阅读JSX渲染函数来理解业务逻辑,但组件之间的联系较弱,ref引用相互隔离,难以构建复杂的交互组件。配置组件需要编写的代码较少,但组件内部渲染是在一个黑盒中,用户很难理解组件的逻辑,扩展性较弱。对于Form表单、Select复选框等基础组件,建议采用组合类型,有利于用户组织业务代码,复杂的交互组件可以采用配置类型。复合组件最具代表性的实践是AntDesign。整个组件库的API设计严格遵循复合优先的原则,为同一组件的不同平面提供复合结构,使其兼具可扩展性和易用性。达到了很高的标准。下图演示了开发具有两种组件类型的选择框的演化模型。选择简易框、组合型和配置型,可以提供清晰易用的界面。与更复杂的Select框组相比,组合类型组件通过提供新的子组件,仍然可以保持简单的API调用。配置组件有两种实现方式:提供新属性或扩展原有属性,这两种方式都会产生一定的认知成本。对于需要自定义的Select框组,复合组件得益于JSX的嵌套结构,可以非常从容地提供自定义API。配置组件要实现同样的功能,需要再次展开属性配置。受控组件和非受控组件还有另外一种表达方式:无状态组件和有状态组件。受控组件内部只负责显示,外部只提供回调来表达对变化的期望,其最终行为完全由外部驱动。不受控制的组件在内部处理某些行为并且不强制执行外部状态同步。官方推荐输出无状态的受控组件,但是有状态的组件在项目开发中还是很有必要的。受控组件在其自身级别调节单向数据流,并可与其他数据层框架集成。然而,要开发一个复杂的受控组件,开发者可能需要提供无数的接口和回调。不受控制的组件更聪明,组件可以独立维护状态,但开发人员往往懒得做状态同步。当上层组件重新渲染时,不受控制的组件会失去内部状态,失忆,日常开发中的大部分bug也因此而来。我们经常通过内部是否有状态来衡量一个受控组件和一个非受控组件,但是完全遵守这个标准将很难提供一个大而易用的受控组件,所有状态都是外部控制的,用户需要编写大量的配置代码来运行一个大型组件,使用成本极高。官方的方案采用了两者结合的方式来处理控制和易用性之间的矛盾。下图显示了Input组件可以接受的参数类型。根据类型定义,可以推导出以下三种使用模式,分别对应一种受控用法和两种非受控用法。开发受控和非受控组件对组件本身的开发和维护都有更高的要求,难度随着组件本身的复杂度而增加。但对于组件用户来说,这种组件组合最适合快速开发和后期代码调优。任何具有输入输出特性的组件(各种形式、配置+回调组件)都可以参考上述类型定义提供API。综上所述,React组件本质上是JS函数的另一种形式。所有与功能相关的思想都可以体现在组件中。每个组件都有其适用的场景。开发大型Web项目需要使用不同类型的组件。如何做出合适的匹配,需要长期的开发和积累,在实际项目中找到最优解。
