这是我参与「第五届青训营 」笔记创作活动的第2天。
我们知道,在编写代码的时候,实现了功能还远远不够,写出质量合格的代码才能算是大功告成,针对如何写出更好的JavaScript代码这个问题,这节课我们将学习写好JavaScript的三条实用编写原则,他们分别是:
- 各司其职:让HTML、CSS、JavaScript职能分离。
- 组件封装:好的UI组件具备正确性、扩展性、复用性。
- 过程抽象:应用函数式编程思想。
接下来我们将一一学习这些原则。
各司其职
思考以下问题:如何实现简单的一键换肤功能?对于初学者,可能会很快地写出以下代码:
版本一:
对于上面的代码,我们给出第二种写法:
版本二:
两种写法有何区别?版本二有何优点?
版本一直接使用JavaScript修改了CSS,而版本二将两者分离出来,逻辑更加清晰直观,代码更加简洁。
那版本二是不是最优解呢?答案是否定的,我们来看看接下来的版本三。
版本三:
版本三与版本二不同的点在于,版本三只有HTML和CSS,没有JavaScript,我们要实现的功能是修改CSS,所以我们很容易想到,能不能让CSS来完成自身的修改,因此就有了版本三,进一步实现职能分离,各司其职。
由上面的案例我们可以得出以下结论:
- 让HTML、CSS、JS各司其职
- 应当避免不必要的由JS直接操作样式
- 可以用class来表示状态
- 纯展示类交互寻求零JS方案
组件封装
接下来我们将学习第二个原则----组件封装,我们将通过轮播图的案例进行学习:
首先我们思考如何初步实现轮播图的功能。
轮播图本质上是一个典型的列表结构。我们可以使用无序列表ul元素来实现整体结构。
然后我们需要把多个图片重叠在同一个位置,这一点可以通过绝对定位实现。
轮播图切换的状态可以使用修饰符(modifier)。切换动画可以用transition实现。
JS代码定义5个方法用于控制滑动,代码如下:
实现了图片的轮播后,我们还需要在底部添加一个“4个小圆点”的控制组件,代码如下:
我们使用自定义事件来解耦。
到此我们初步实现了轮播图的完整功能。但是完成代码后,我们可以思考代码是否还可以进行改进?
我们发现如果想改变轮播图中的某个控制元素,那么它的HTML代码得改,CSS代码得改,JS代码也得改,这样子改动的成本很大,有没有什么办法能避免这种情况?这就涉及到我们接下来要讲的插件化。
重构:插件化
我们可以通过以下方式进行解耦:
- 将控制元素抽取成插件
- 插件与组件之间通过依赖注入方式建立联系
重构:模板化
- 将HTML模板化,更易于扩展
重构:抽象化
- 将组件通用模型抽象出来
总结如下:
过程抽象
过程抽象是用来处理局部细节控制的一些方法,它是函数式编程思想的基础应用。
我们来看一个例子,这段代码可以控制点击列表2秒后该列表消失:
但它存在一个bug,当用户在2秒内点击多次,事件会多次触发,第二次触发时该元素已经消失,我们想要的是只触发一次。
对于addEventListener,我们可以直接用once参数,但在其他情况没有once参数可用,这时候我们可以考虑自己写一个once函数进行包装:
为了能够让“只执行一次”的需求覆盖不同的事件处理,我们可以将这个需求剖离出来,这个过程我们称为过程抽离。
在上面的例子中,我们实际是使用了高阶函数实现过程抽离。什么是高阶函数呢?
高阶函数具有以下特点:
- 以函数作为参数
- 以函数作为返回值
- 常作为函数装饰器
本节小结
本节课我们学习了JavaScript编码三条很重要的原则----各司其职、组件封装、过程抽象。在了解这些原则之后,我们应该尽量在以后的编码中去思考并应用这些原则。除此之外,JavaScript还有很多其他的编码原则值得我们去学习,在未来的路上,我们需要不断学习这些原则并将其应用到自己的编码中,不断提高自己的编程能力。