组件化产生背景,为什么要组件化开发?
-
web应用日趋复杂,传统开发成本高;
随着网络普及web应用得到了迅速的发展。很多web应用生态为了提高用户体验的友好行,把许多与服务器交互的逻辑放到了客户端。用户交互,前后端数据交换,前端数据渲染,导致客户端开发的复杂性空前提高。 -
前端生态html+css+JavaScript导致的
作为前端的三大技能树html+css+JavaScript开发的特性。原始的html标签不能定制化的特征,导致很多时候我们都需要自己结合实际开发需求对html进行二次封装;css是global作用域会导致统一页面不同css文件作用域的污染。
以上的环境导致了在前端开发的环境中,很多代码耦合性高,复用性低,也导致了开发效率低下。如何保证质量的情况如何能够做到高效开发?
像解决其它问题一样参考已有成熟的解决方案——组件化开发(例如使用promise/async await解决callback hell问题)。 -
组件化开发可以带来以下几个好处:
1.对原始html进行封装,提高代码的复用率,提示开发效率
2.对css进行作用域隔离,提高代码可维护性
3.统一交互方式(props/attribute/event)降低认知成本
什么是前端组件?
通过对样式(css)模版(html)逻辑(js)的封装,构成一个内部作用域隔离的功能模块。组件通过props/attribute和Event进行统一的通信方式;组件拥有lifecycle钩子函数可以方便的对自身状态进行管理。通过使用组件来可以提升代码的可维护性和复用性。
组件化进程
jquery时代如何编写组件
刚入行的那一年,jquery如火如荼的占领着前端开发的各个角落,这时候并不是没有组件化,反而是各种组件遍地开花,轮播图组件(Swiper),Tab组件,日期选择组件,这时候的组件编写方式如下
1.首先需要在头部引入一个样式,然后再引入js依赖包
<link rel="stylesheet" href="dist/css/swiper.min.css">
<script src="dist/js/swiper.min.js"></script>
2.实例化组件
<script>
var mySwiper = new Swiper ('.swiper-container', {
// ...options
})
</script>
这样一个轮播图就出来了,组件的内部实现也进行了很好的封装。但是这样的做法也会带来一定的问题,引入的css和JavaScript会污染全局作用域,导致和现有代码的样式和js命名空间的冲突。
三大框架时代
以Vue单文件组件为例
<template>
<div class="example">{{ msg }}</div>
</template>
<script>
export default {
data () {
return {
msg: 'Hello world!'
}
}
}
</script>
<style scoped>
.example {
color: red;
}
</style>
通过webpak打包工具对css和JavaScript的作用域都进行了很好的隔离。
如何设计组件化设计
- 模版解析
模版是组件的内容承载部分,其实就是html。市面上的模版的写法有两种:第一种是jsx,需要通过webpack的jsx包处理;第二种是html模版,通过html解析的方法来处理模版。jsx可以更方便的表达模版展示逻辑,html模版更接近于原生html,认知成本较低。这也是Vue入门相较于React门槛更低的原因吧。 - css
css在组件化里面需要解决的问题就是作用域隔离。css作用域隔离有两个方向。- 由于css有子代选择器,所以我们可以在组件外层自定义一层父级选择器。可以使用sass这种css预处理器做;也可以用使用css解析器,生成css的抽象语法树,在外层添加一个父选择器。
- 解析模版时找到css文件对应的className,然后重新命名className(css-in-js)
前者实施起来较为简单,但是没有从根本上解决css作用域问题,后者实施起来就像对繁琐,但是作用域隔离的更彻底。
- lifecycle
生命周期是组件的一个重要概念,可以让我们方便的对不同状态下的组件结合业务进行逻辑编写。
一般生命周期分为三个阶段- 挂载
挂载就是组件把DOM对象添加到页面(DOM树结构),这时候我们可以获取到原生的DOM对象,使用原生的DOM方法,添加事件监听器等。 - 更新
更新是组件由于内部或者外部传入数据需要组件重新渲染,这个地方可以对更新数据进行对比,做性能优化。 -
销毁
组件从DOM树移除,这时候需要我们对组件的事件监听器做移除处理等。
React生命周期示意图
- 挂载
- props&attribute
props和attribute是组件间最主要的一种通信方式,它是一种自上而下很自然的传递数据的方式。这种方式可以让数据自上而下有组织的传播下去。但是这种方式并不能完全解决组件通信的所有问题,子组件对父组件进行通信并不方便;如果组件层级过深,这种方式传递特别繁琐。 - event
event也是组件间通信方式的一种,它采用发布/订阅这种方式进行通信。event正是去解决props/attribute不能进行数据逆向传播的问题,过深层级组件数据传递问题。但是如果过度使用event这种通信方式会导致代码的可维护性变得很差。
在前端三大框架鼎足而立的今天,不论是Vue,React,还是Angular都有组件化的解决方案,在工作中我们需要结合实际业务去判断如何抽象和拆分组件形成更好的组件化开发方案。
网友评论