我们在业务中经常会自行定义ui 控件,这确实能达到复用的目的,但是它不是常常有效,但是有时它也会表现的糟糕,比如样式错乱。
插入自定义卡片,样式错乱了
Web Components 的出现就是为了解决这些问题。Web Components是一套允许定制元素并且可重用的技术标准。
Web Components 主要包含以下三部分:
想要自定义一个元素标签,需要用到customElements
这个对象,具体使用如下:customElements.define(name, constructor) 定义元素内容
class BookCard extends HTMLElement {
constructor() {
super();
this.innerHTML = `
<span>custom element span</span>`;
}
}
if (!customElements.get("book-card")) {
customElements.define("book-card", BookCard);
自定义元素中的样式会影响主DOM中的样式,无法达到很好的隔离效果
constructor() {
this.innerHTML = `
<span>custom element span</span>`;
//自定义元素样式会影响外部span样式
let style = document.createElement("style");
style.textContent = "span {font-weight:bold}";
this.appendChild(style);
}
因此 Shadow DOM
就此出现
创建shadow DOM 方法如下
element.attachShadow({mode: ‘open’})
mode 可以有以下取值:
const shadowHostElement = document.querySelector('.shadow-host');
const shadowRoot = shadowHostElement.attachShadow({mode: 'closed'})
//shadowHostElement.shadowRoot 为null
使用 attachShadow创建一个Shadow Tree之后其DOM 结构是与主文档隔离的,其具体结构如下:
Shadow DOM 的一大优点是能将 DOM 结构、样式、与主文档结构隔离,很适合做组件的封装,避免组件污染宿主。其具体以下隔离特性:
constructor() {
//...
const shadowRoot = this.attachShadow({ mode: "open" });
let style = document.createElement("style");
//该样式不会影响主文档的span
style.textContent = "span {font-weight:bold}";
shadowRoot.innerHTML = `<span class="fz30">custom element span</span>`;
shadowRoot.appendChild(style);
}
除了使用 innerHTML
定义DOM结构外,我们还可以使用<template>标签来定义内容。template 是定义的一个HTML标签元素, 可以编写不呈现在页面中显示的标记模板。然后它们可以作为自定义元素结构的基础被多次重用。在 <template>元素中我们还可以定义css 样式。
<template id="book-card-template">
<style>
//...
</style>
<p class="title">小王子</p>
<p class="desc">安托万·德·圣-埃克苏佩里</p>
<p class="price">¥25.00</p>
</div>
</template>
HTML 模板的另一个好处是可以像在Vue 中使用 slot,用来作组件的差异化,具体使用如下:
// template 用于自定义元素template-book-card-slot中
<template id="template-book-card-slot">
//其他dom 内容
<slot name="btn">slot占位</slot>
</template>
当使用template-book-card-slot
可以使用slot=btn 的元素
来自定义DOM结构。
上面主要分享 Web Components相关内容,总的来说,Web Components 是由一系列API 的组合: Custom Elements(自定义封装元素标签)
、Shadow DOM(样式隔离)
、template(灵活定义DOM 结构)
,主要用于组件封装等场景中。