一套技术的组合,能提供给开发者组件化开发的能力。
那什么是组件化呢?
其实组件化并没有一个明确的定义,不过这里我们可以使用 10 个字来形容什么是组件化,那就是:对内高内聚,对外低耦合。对内各个元素彼此紧密结合、相互依赖,对外和其他组件的联系最少且接口简单。
可以说,程序员对组件化开发有着天生的需求,因为一个稍微复杂点的项目,就涉及到多人协作开发的问题,每个人负责的组件需要尽可能独立完成自己的功能,其组件的内部状态不能影响到别人的组件,在需要和其他组件交互的地方得提前协商好接口。通过组件化可以降低整个系统的耦合度,同时也降低程序员之间沟通复杂度,让系统变得更加易于维护。
大部分语言都能实现组件化,归根结底在于编程语言特性,大多数语言都有自己的函数级作用域、块级作用域和类,可以将内部的状态数据隐藏在作用域之下或者对象的内部,这样外部就无法访问了,然后通过约定好的接口和外部进行通信。
JavaScript 虽然有不少缺点,但是作为一门编程语言,它也能很好地实现组件化,毕竟有自己的函数级作用域和块级作用域,所以封装内部状态数据并提供接口给外部都是没有问题的。
既然 JavaScript 可以很好地实现组件化,那么我们所谈论的 WebComponent 到底又是什么呢?
阻碍前端组件化的因素 如果两个人分别负责开发分别实现了 p 标签的属性color样式属性,那么在测试阶段可能没有什么问题,不过当最终项目整合的时候,其中内部的 CSS 属性会影响到其他外部的 p 标签的,之所以会这样,是因为 CSS 是影响全局的。
渲染引擎会将所有的 CSS 内容解析为 CSSOM,在生成布局树的时候,会在 CSSOM 中为布局树中的元素查找样式,所以有两个相同标签最终所显示出来的效果是一样的,渲染引擎是不能为它们分别单独设置样式的。
除了 CSS 的全局属性会阻碍组件化,DOM 也是阻碍组件化的一个因素,因为在页面中只有一个 DOM,任何地方都可以直接读取和修改 DOM。所以使用 JavaScript 来实现组件化是没有问题的,但是 JavaScript 一旦遇上 CSS 和 DOM,那么就相当难办了。
WebComponent 组件化开发 现在我们了解了CSS 和 DOM 是阻碍组件化的两个因素,那要怎么解决呢?
WebComponent 给出了解决思路,它提供了对局部视图封装能力,可以让 DOM、 CSSOM 和 JavaScript 运行在局部环境中,这样就使得局部的 CSS 和 DOM 不会影响到全局。
了解了这些,下面我们就结合具体代码来看看 WebComponent 是怎么实现组件化的。
前面我们说了,WebComponent 是一套技术的组合,具体涉及到了Custom elements(自定义元素)、Shadow DOM(影子 DOM)和HTML templates(HTML 模板),Web_components
首先,使用 template 属性来创建模板。利用 DOM 可以查找到模板的内容,但是模板元素是不会被渲染到页面上的,也就是说 DOM 树中的 template 节点不会出现在布局树中,所以我们可以使用 template 来自定义一些基础的元素结构,这些基础的元素结构是可以被重复使用的。一般模板定义好之后,我们还需要在模板的内部定义样式信息。