Better

Ethan的博客,欢迎访问交流

前端组件拆分重构的思考

深夜是最适合安静思考的时间,本计划本周末好好学习如何使用 Taro 开发小程序,因为早就计划开发一个给自己使用的小程序,因为一些事情搁置了,但是追剧去了,追剧害人呀,还是看电影好,没那么多悬念,哈哈。言归正传,最近一周的工作内容将一个大的组件拆分成多个小组件,具体实施的过程中还是有所感悟和思考的,就在这里记录下来吧。

拆分背景

随着项目的推进,无论的逻辑代码 JS,还是 UI 模板,一个组件可能会变得原来越大,主要原因有两方面吧

  • 前期没预计到该组件将来会变得很复杂,因此前期拆分的粒度不够细
  • 由于项目时间紧,或组件状态管理十分复杂,组件拆分会遇到一些困难,因此没有拆分

接下来谈谈为什么需要组件拆分

  • 软件性能考虑:拆分组件一定程度可以提高性能,因为组件重新渲染的范围也会更小
  • 项目可维护性:作为一个开发者,谁也不想看到一个文件一打开,就上百个变量再加上百个函数摆在面前,这对谁而言都是无法接收的,尤其是新人更是如此,这一点我深有感悟
  • 代码可复用性:组件拆分粒度细,可以提高复用度,这次需求是工具栏的优化,涉及到众多的按钮,而摆在我面前的一个难题就是,有三个路由组件都需要工具栏,因此里面部分代码高度冗余,我估计是由于时间紧张,当初的开发人员并没有及时抽象出来。倒是技术债这种东西,越早解决,所付出的成本就越小

难题与应对方式

这次我碰到的难题如下

  • 不同的路由组件,并不需要所有按钮元素,而是有些需要有些则不需要,你可以将需要的按钮组件一个一个写在对应的组件里,但是那样的话,还是组件的 UI 依旧会显得很啰嗦
  • 按钮元素并不是完全独立的,比如他们的 disabled 或 active 状态,就和其他按钮的状态相关,比如要实现互斥功能等
  • 按钮过多,整理蒙圈了,因为害怕出错,再加上我有代码洁癖,因此格外小心,但是心里负担真的很重

针对上述问题,我考虑的解决办法如下

  • 构造一个 toolBuilder 组件,采用动态组件的方式,动态渲染需要的组件
  • 在 toolBuilder 组件中管理各个按钮 disabled、active 状态和互斥功能等,比如互斥,可以给按钮定义相同的 name,name 相同即互斥
  • 人对于繁琐的工作总是出错的,因此针对第三个问题,我的解决办法是建立一个 CheckList,可以我的步骤如下
    1. 根据 HTML 模板,找出属于该组件的 CSS 样式,抽离出来
    2. 将对应的 HTML 抽离到单独的组件
    3. 事件处理函数提取到单独的组件
    4. 调通逻辑,主要是组件的 props 和 state 管理

优化点:我写代码的过程中,发现很多按钮组件,都依赖 service(angular) 中相同的一些可观察对象,在 angular 中,这一部分代码,我自认为是最麻烦的部分,因为我需要注册它的变化,然后组件销毁时候,我还要取消对它的注册。明天等我去公司,计划将这部分逻辑都提取到 toolBuilder 中,然后采用 props 的方式传递给子组件。

思考

公司的项目采用的 service 在组件中共享数据的方式,同时也被广泛的用来拆分逻辑,不禁让我思考 service 在这两种场景中可能存在的问题。

先来谈谈用来拆分逻辑的方式,为了避免组件变量和逻辑过多,很多时候我们会将变量和函数统统移步到 service 中,甚至没有在 component 中做一层转换,而是采用 public 的方式注入到组件中,这样在 UI 层,直接调用 service 中的变量和函数,这在 Vue 和 React 中是行不通的,这也算是 angular 的一个特色了,在这次重构中,我发现这样会存在几个问题

  • 对于 private 修饰的 service,如果函数中没有对它进行引用了,此时 IDE 会很智能的提示我,对于有代码洁癖的我,可以直接放心的删除掉该部分引用,但对于 public 修饰的 service,IDE 无法对其智能检查,因为它不知道 UI 中是不是直接引用了,甚至其他模块会不会直接持有其实例且调用了对应函数,对于他们我就不太敢删除,如果要删除,我花的时间成本会非常高,而且并不可靠
  • 另外关于这个我的思考就是,都考虑到使用不同的 service 来拆分逻辑了,我们是不是应该首要考虑的是拆分成多个组件呢,我觉得这个观念的转换很有必要,也不会导致一个组件依赖过多的 service

再来谈谈使用 service 在组件中共享数据的方式,对比 Vuex 和 Redux,我觉得它可能存在的问题有

  • 状态修改难以追踪,所有组件都可以任意修改
  • 无法监听其变化,比如 onChange 事件无法得到组件中依赖的 service 数据是否变化了,我们只能使用观察者模式的大成者 RxJS,但是它的管理确实麻烦
  • 导致组件重新渲染的可能超级多,现在的开发模式讲究这种单一,过多势必会引入复杂度

在来谈谈 React 和 Angular,在这次重构中,我想起最初关于 React 和 Angular/Vue 的差别

Angular/Vue 都是采用的增强 HTML 的方式,提供一些指令,使 HTML 具有一定的逻辑能力,而 React 不同,它采用的是增强 JS 的能力,使的 JS 可以直接操纵 HTML

关于上一点区别,我这周突然就有了很深的感悟,增强 JS 的能力势必能带来更大的灵活性,因为其是一门图灵完备语言。



留言