Web Components
组件化
组件化是一种软件工程的概念,它将一个复杂的系统分解为一个个独立的、可复用的模块,
这些模块可以被独立开发、测试和维护。组件化的关键是将系统分解为可复用的模块,并将
这些模块组合在一起形成一个完整的系统。
组件化的好处:
- 代码复用率提高,带来的是工作效率的提升
- 代码可维护性、可读性提升
- 团队效率提升
什么是 Web Components?
Web Component 是一种用于构建可复用用户界面组件的技术,开发者可以创建自定义的 HTML 标签,并将其封装为包含逻辑和样式的独立组件,从而在任何 Web 应用中重复使用。
每个 Web Component 都具有自己的 DOM 和样式隔离,避免了全局 CSS 和 JavaScript 的冲突问题。它还支持自定义事件和属性,可以与其他组件进行通信和交互。
不同于 Vue/React 等社区或厂商的组件化开发方案,Web Component 被定义在标准的 HTML 和 DOM 标准中。它由一组相关的 Web 平台 API 组成,也可以与现有的前端框架和库配合使用。
Web Component 的兼容性良好,可以在现代浏览器中直接使用,也可以通过 polyfill 兼容到旧版浏览器(IE11 理论上可以兼容,出于初步调研的考虑,本文不对兼容性作过多探讨)。
customElements
customElements
是 Window
对象上的一个只读属性,接口返回一个
CustomElementRegistry
对象的引用,可用于注册新的 custom element
,或者获取之
前定义过的自定义元素的信息。
自定义元素
自定义元素是 Web Components 的一种,它允许你创建一个自定义的 HTML 元素,这些元素
可以被其他开发者使用,并且可以与现有的 Web 组件库整合。
组件编写
<template id="person-tem">
<div>
<h1></h1>
</div>
</template>
使用组件
<person-template></person-template>
js代码
class Person extends HTMLElement {
constructor() {
super()
let shadow = this.attachShadow({ mode: 'closed' });
let templateElem = document.getElementById('person-tem');
let content = templateElem.content.cloneNode(true);
content.querySelector('h1').textContent = 'hello'
shadow.appendChild(content);
}
}
customElements.define('person-template', Person)
首先我们定义了shadow
,shadow
是Web Components
中的一个重要概念,它是一个DOM树,但是它和普通的DOM树有所不同,它是一个封闭的DOM树,外部无法访问到它的内容,我们可以通过attachShadow()
方法来创建一个shadow
,attachShadow()
方法接收一个参数,mode
,mode
有两个值,open
和closed
,open
表示外部可以访问到shadow
中的内容,closed
表示外部无法访问到shadow
中的内容,我们这里使用的是closed
,因为我们不希望外部访问到shadow
中的内容,
然后我们通过document.getElementById()
方法获取到模板,然后通过content.cloneNode()
方法克隆模板,然后将克隆的模板添加到shadow
中,这样我们就完成了自定义元素的定义,
组件样式
<template id="person-tem">
<style>
h1{
color:red;
}
</style>
<div>
<h1></h1>
</div>
</template>
这样就改变了颜色
完整的dom结构
组件封装
我们的html还是只保留使用组件的代码
<body>
<person-template></person-template>
</body>
<script type="module">
import Person from './web.js'
customElements.define('person-template', Person)
</script>
把template
和组件定义都抽离出去,放在一个js文件中
const template = document.createElement('template')
template.innerHTML = `
<style>
h1 {
color: red;
}
</style>
<div>
<h1></h1>
</div>
`
export default class Person extends HTMLElement {
constructor() {
super()
let shadow = this.attachShadow({ mode: 'closed' });
let content = template.content.cloneNode(true);
content.querySelector('h1').textContent = 'hello'
shadow.appendChild(content);
}
}
上面有一个小的改变,我们template
是动态创建出来的,组件的定义没有太大的变化,最后在使用的时候,我们通过import
引入,并关联组件
通过这个例子,我们可以发现Web Components
的使用非常简单,他的实现不是一个单一的技术,而是由DOM API
和 HTML
规范所组成。它其中就包含了:
- custom elements
- shadow dom
- html templates
- ES Modules
优势
Web Components优势都是建立在它是Web原生提供的基础上的,框架会变,但是Web原生不会变
- 浏览器原生支持,无需引入第三方库
- 可复用性,组件可以在不同的框架中使用,因为是原生的语法,所以我们可以在任何其他框架中使用,而不用考虑框架的束缚
- 组件样式封装,组件样式不会影响外部样式,样式隔离带来的安全空间让我们不用再考虑样式污染问题
限制
- CSS 的隔离,导致和外部 CSS 交互比较难
- document 、 window、 document.body、 document.head是不可配置的,不能被覆盖。
服务器端渲染(SSR)仍然存在问题,在服务器上渲染 Web Component 没有标准,因此每个框架的做法都略有不同 - shadow dom的内容是不可访问的,这意味着我们在这里可能会遇到问题,比如全局弹窗,Web Componewnt中的内容获取,与window,document等交互可能并不如我们往常期望的效果一样
总结
Web Components 是一种新型的前端开发技术,它允许你创建可重用的自定义标签,这些标
签可以被其他开发者使用,并且可以与现有的 Web 组件库整合。