现在的前端开发基本离不开 React、Vue 这两个框架的支撑,而这两个框架下面又衍生出了许多定义组件库:
这些组件库的出现,让我们可以直接使用已经封装好的组件,而且在开源社区的帮助下,出现了很多的模板项目( vue-element-admin、Ant Design Pro ),能让我们快速的开始一个项目。
虽然 React、Vue 为我们的组件开发提供了便利,但是这两者在组件的开发思路上,一个是自创的 JSX 语法,一个是特有的单文件模板的语法,两者的目标都是想提供一种组件的封装方法。毕竟都有其原创的东西在里面,和我们刚开始接触的 Web 基础的 HTML、CSS、JS 的方式还是有些出入的。今天介绍的就是,通过 HTML、CSS、JS 的方式来实现自定义的组件,也是目前浏览器原生提供的方案:Web Components。
什么是 Web Components?
Web Components 本身不是一个单独的规范,而是由一组DOM API 和 HTML 规范所组成,用于创建可复用的自定义名字的 HTML 标签,并且可以直接在你的 Web 应用中使用。
代码的复用一直都是我们追求的目标,在 JS 中可复用的代码我们可以封装成一个函数,但是对于复杂的HTML(包括相关的样式及交互逻辑),我们一直都没有比较好的办法来进行复用。要么借助后端的模板引擎,要么借助已有框架对 DOM API 的二次封装,而 Web Components 的出现就是为了补足浏览器在这方面的能力。
流行趋势
- Twitter:嵌入式推文
- YouTube:该站点是使用 Web Components 构建的
- Electronic Arts:该站点也是使用 Web Components 构建的
- Adobe Spectrum:该站点是一个基于 Web Components 的 UI 框架产品
另外还有维基百科、可口可乐、麦当劳、IBM 和 通用电气 等也使用基于Web 组件的技术和框架。
技术优点
- 原生支持
原生支持意味着可以不需要任何框架即可完成开发,同时也意味着这将有更好的用户体验,更低的网络请求,以及更稳定的迭代前景。并且我们一直都有在使用这项技术,比如 input, video,select 等等,其实他们都是标准的原生组件,只是如今我们自己也可以使用这项技术去创造这些组件。 - 无排他性
这是原生支持的一个延伸表现,作为浏览器原生支持也就意味着它可以在任何环境中使用,例如在 React,Angular,Vue 中使用他们。同时也意味着对 Web Components 的支持无需大刀阔斧的颠覆现有逻辑体系,你可以从局部开始进行改造。 - 无依赖性
这一点同样是原生支持的一个延伸表现,通过提供连接特定 Web 组件的选项,而无需将框架的依赖项导入到项目中,您就可以拥有优于流行框架的优势。
让我们想象一个场景:如果您喜欢用 React 创建的小部件,并且想将其包含在您的项目中,则必须首先包含整个 React 库,然后才能导入您喜欢的小部件。相反,如果您选择使用 Web 组件创建的小部件,您可以立即将其插入到项目中——这一切都归功于这项技术的原生特性。
如何使用 Web Components?
Web Components 中包含的几个规范,都已在 W3C 和 HTML 标准中进行了规范化,主要由三部分组成:
- Custom elements(自定义元素):一组 JavaScript API,用来创建自定义的 HTML标签,并允许标签创建或销毁时进行一些操作;
- Shadow DOM(影子DOM):一组 JavaScript API,用于将创建的 DOM Tree 插入到现有的元素中,且 DOM Tree 不能被外部修改,不用担心元素被其他地方影响;
- HTML templates(HTML模板):通过
、
直接在 HTML 文件中编写模板,然后通过 DOM API 获取。
shadow DOM
Web 组件的一个重要方面是封装——能够将标记结构、样式和行为隐藏起来并与页面上的其他代码分开,这样不同的部分就不会发生冲突,并且代码可以保持整洁。Shadow DOM API 是其中的关键部分,它提供了一种将隐藏的分离 DOM 附加到元素的方法。
性能优势-组件隔离(Shadow Dom)
Shadow DOM 为自定义的组件提供了包括 CSS、事件的有效隔离,不再担心不同的组件之间的样式、事件污染了。这相当于为自定义组件提供了一个天然有效的保护伞。
Shadow DOM 实际上是一个独立的子 DOM Tree,通过有限的接口和外部发生作用。我们都知道页面中的 DOM 节点数越多,运行时性能将会越差,这是因为 DOM 节点的相互作用会时常在触发重绘(Repaint)和重排(reflow)时会关联计算大量 Frame 关系。
- Shadow host:Shadow DOM 附加到的常规 DOM 节点。
- Shadow tree:Shadow DOM 内部的 DOM 树。
- Shadow boundary:Shadow DOM 结束的地方,普通 DOM 开始的地方。
- Shadow root:Shadow tree的根节点。
你可以以与非影子节点完全相同的方式影响影子 DOM 中的节点——例如,附加子项或设置属性、使用 element.style.foo 为单个节点设置样式,或在