浅谈前端组件设计

与仅承担数据处理逻辑的后端不同,前端需要负责界面渲染、数据处理、和接口调用,在框架诞生前,更多地是编写页面维度的顺序脚本代码。随着前端继续的持续发展,ES6推出了class语法糖,React提出了函数式组件,Vue则以模版语法的形式组织代码,前端代码逐渐从“平铺”转变到了“层级”结构,从“面向过程”进阶为“面向对象”,前端组件也成为了近几年来的热门议题。,“组件是对数据和方法的简单封装,是软件中具有相对独立功能、接口由契约指定、和语境有明显依赖关系、可独立部署、可组装的软件实体。”这段百科中摘取的组件定义,揭示了组件所需要具备的特性:功能独立、约定一致、可集成、服务于场景。,在软件工程中,软件设计是软件开发流程中的必要阶段,在需求分析后、软件开发前进行。软件复杂度是每一个项目演进的产物,随着需求和代码行数的增加,复杂度将持续提升。软件设计的优劣为对复杂度带来的影响是不同的,优雅、合理的设计使待开发的代码复杂度可控,而拙劣的设计将会给软件带来无序、偶然的复杂度变更。一个优秀的前端组件需要在满足需求的前提下,具备高易用性和良好的可扩展性,这是我们进行前端组件设计的目标。,组件既生于页面,又能够独立于页面。我们不能将整个页面杂糅为一个组件,也不能将每一小块UI都封装为组件。前端组件按类型可以分为容器组件、功能组件和展示组件,一个优秀的组件应该保证:功能内聚、样式统一、并且与父元素仅通过Props通信。,组件的封装粒度并不是越小越好,很多时候一个组件是在其他一个或多个组件的基础上开发的,无法完全以功能点的数量衡量是否遵循单一职责原则,组件开发者需要根据组件功能和目标来确定组件封装粒度:,:InputTag组件 在 Input、Tag 的基础上,增加了部分交互功能,API整合了两个组件的属性,作为一个全新的组件提供给开发者使用。相似的,InputNumber、AutoComplete、Mentions等组件也是基于单一职责原则封装的特定功能组件。,图片,:图片预览功能通常依托着图片组件使用,在实际系统中,唤起图片预览的触发器不一定是图片,可能是按钮或其他触发事件,因此预览组件需要单独提供给开发者使用。预览组件作为 Image 的内部组件,开发者能够以Image.Preview、Image.PreviewGroup的方式使用,并提供左右切换、图片缩放等功能,用户可以通过 srcList、visible、actions、scales等API来控制并定制化预览组件。,图片,图片,一个易用的组件,使用者无需阅读文档或仅快速浏览文档即可上手使用,并且应当在使用过程中给予清晰的注释和代码提示。希望以下API编写建议能够给组件开发者一些参考:,使用Props存在的问题?,当我们需要实现一个较为复杂的卡片需求组件时,为了最大程度地还原UI、减少用户的样式开发成本,首次设计时我们会设计出这样的API:,可以看到,这个业务卡片组件是由多个不同组件组合而成,其承载了渲染和操作(选中操作、图片切换和弹层操作),这个设计的缺陷是显而易见的:,如果以插槽的方式对Card组件进行改造,通过内部组件间的组合来实现需求,避免了大量组件Props的堆砌,层次清晰、可读性高,这样的组件结构明显易用性更高。,什么是插槽(Slot)?,图片,Slot是Vue框架提出的概念,可以理解为临时占位,可以用其他组件进行填充,Slot能够实现父组件向子组件分发内容的功能。Vue框架中提供了,Slot(内部组件)的使用时机?,开闭原则:对扩展开放,模块的行为可以被扩展;对修改关闭,模块中的源代码不应该被修改,在前端组件中,应该提供对应的API属性或方法来支持额外的功能,给予开发者更充分的扩展空间,而不是有部分需求无法满足时放弃使用组件。以 Cascader组件 为例(以下例子若无特殊说明,均来自Arco组件库),在通常情况下,仅需要使用左侧的基础选择器即可满足需求。,图片,此时若开发者需要在级联选择器底部添加操作按钮或文字展示,可能会直接修改组件源代码、甚至放弃使用该组件。作为组件开发者,为了提升组件可扩展性,在此处增加了 dropdownRender​属性,接收一个返回 ReactNode​ 的函数,并将此 ReactNode 渲染在级联选择器的特定位置。,图片,与此类似的,还有 renderFooter、renderOption、renderFormat 等API,这些API实现难度并不高,一定程度上将DOM元素的掌控权交予组件使用者,作为通用组件,为开发者提供了部分功能和样式的可扩展性。我们在设计前端组件时,多多留意组件中能够接管给使用者的渲染逻辑和操作逻辑,并将这些逻辑暴露出去。,组件开发前,整理组件所需实现的功能,并以功能为维度设计组件API。以下是一个设计移动端选择器的例子,这个选择器需要支持单选、多选和时间选择,于是这样写了第一版API,它可以满足我们当前的选择器需求。,在后续迭代中发现还有地区选择和级联选择的需求,选择器需要进行优化更新,在以上API的基础上只能通过添加cascader、region两个布尔值字段用于标识不同选择需求。这样做的缺陷是很明显的,每当我们新增不同类型的选择功能,都需要新增一个API字段,并且这些字段还是互斥关系。理清问题后,更新了第二版API。在组件库中很多API都设计为常量枚举值的形式,即使其只有两个取值,这样扩展性相较于布尔值类型更好。,除上述例子外,还可以利用ts的泛型和可选类型来实现API扩展,例如 Table 组件的pagination、border等字段,既可以直接设置为true/false,也能够以对象的形式进行更详细的配置。,图片,首次接触headless概念是在chrome浏览器中,在headless模式下用户无需看到网页界面即可进行网页操作,现在广泛用于web自动化测试和爬虫场景中。与之相似的,Headless UI 是基于 React Hooks 的组件开发设计理念,强调只负责组件的状态及交互逻辑,不关注组件的样式实现。其本质思想其实就是关注点分离,将组件的“状态及交互逻辑”和“UI 展示层”实现解耦。,Headless UI目前有两种主流实现方式,其一是将组件划分为多个原子组件,使用者可以通过填充组件或修改样式的方式来实现自己的需求,其二是以Hooks的方式暴露内置交互功能的子组件属性,使用者可以将这些属性应用于任意组件上,由于没有将样式封装到组件中,Headless组件实现了最大程度的视图层可扩展性。,图片,由于Headless组件的抽象程度较高,所需的设计成本也更高,因此并不适用于所有前端场景。其更适合用于开发横跨多个不同业务或跨端的通用组件,开发者需要在开发底层Headless组件和开发多套组件中衡量成本、作出抉择。,https://arco.design/react/docs/start,https://juejin.cn/post/7160223720236122125,https://juejin.cn/post/6844904032700481550

文章版权声明

 1 原创文章作者:cmcc,如若转载,请注明出处: https://www.52hwl.com/22153.html

 2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈

 3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)

 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023年3月5日 上午12:00
下一篇 2023年3月7日 下午10:34