Web?Components入門教程示例詳解
Web Components不兼容IE
2011年提出Web Components,為了解決代碼復(fù)用問題,早于React、Vue;
相對于React、Vue組件,Web Components是原生組件,不限制接入方的技術(shù),可以接入到React、Vue等技術(shù)框架中
困境
- 兼容性不足,需要主流瀏覽器的支持,需要平緩的過渡
- 沒有標(biāo)準(zhǔn)的數(shù)據(jù)綁定機(jī)制、在處理自定義元素內(nèi)部數(shù)據(jù)、UI更新、組件間參數(shù)傳遞時(shí)不夠便捷和友好,目前來看大多還依賴于操控dom去實(shí)現(xiàn)UI更新
Web Components核心技術(shù)
- 自定義元素
- HTML模板
- 影子Dom
自定義元素

使用 window.customElements.define 自定義html標(biāo)簽元素,自定義元素需要我們用JS封裝一個(gè),我們在html內(nèi)使用的自定義元素custom-button就是該類的實(shí)例;
自定義標(biāo)簽的生命周期 constructor -> attributeChangedCallback -> connectedCallback
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<custom-button></custom-button>
<script>
class CustomButton extends HTMLElement {
constructor() {
super();
console.log("this", this);
const info = document.createElement("span");
info.setAttribute("class", "test_custom");
info.textContent = "自測自定義標(biāo)簽";
var container = document.createElement("div");
container.classList.add("container");
this.append(info, container);
}
}
customElements.define("custom-button", CustomButton);
</script>
</body>
</html>

我們可以看到CustomButton繼承了HTMLElement,也就是繼承了HTML元素的特性,最后我們執(zhí)行了this.append(DOM),也就是將元素內(nèi)容添加到當(dāng)前自定義標(biāo)簽內(nèi),this表示自定義元素實(shí)例
HTML模板(template、slot)

<template>:包含一個(gè)html片段,不會在html初始化時(shí)渲染。主要作用是:通過JavaScript獲取該代碼片段將其放入自定義標(biāo)簽內(nèi)顯示,主要作用于自定義標(biāo)簽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<template id="test_template">
<div class="container">
<span class="test_custom">自測自定義標(biāo)簽</span>
</div>
</template>
<custom-button></custom-button>
<script>
class CustomButton extends HTMLElement {
constructor() {
super();
const dom = document.querySelector("#test_template").content;
this.append(dom);
}
}
customElements.define("custom-button", CustomButton);
</script>
</body>
</html>

我們可以發(fā)現(xiàn)這種寫法相對于前一種方式,更加易讀以及便捷
<slot>插槽:給模板元素傳值,增強(qiáng)模板元素的靈活性和通用性。 slot在使用過程中具備以下特性
- 必須在影子Dom種使用,否則不具備插槽的效果
- 給 Slots 傳值的元素必須是自定義元素的直接子元素,否則傳值失效
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<template id="test_template">
<div class="container">
<span class="test_custom">自測自定義標(biāo)簽</span>
<slot name="userName" slot="userName"></slot>
</div>
</template>
<custom-button>
<div class="name_cls" slot="userName">張三</div>
</custom-button>
<script>
class CustomButton extends HTMLElement {
constructor() {
super();
const dom = document.querySelector("#test_template").content;
this.append(dom);
}
}
customElements.define("custom-button", CustomButton);
</script>
</body>
</html>

通過上圖發(fā)現(xiàn)我們插入的<div class="name_cls">張三</div>并沒有插入到container節(jié)點(diǎn)內(nèi),主要是因?yàn)槲覀兊膕lot沒有用在影子dom種,所以瀏覽器將<div class="name_cls">張三</div>當(dāng)成其正常的元素進(jìn)行渲染了;
<script>
class CustomButton extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: "closed" });
const dom = document.querySelector("#test_template").content;
shadow.append(dom);
}
}
customElements.define("custom-button", CustomButton);
</script>

當(dāng)我們將slot插入在影子dom,可以發(fā)現(xiàn)slot生效了;
另外需要注意的一個(gè)點(diǎn),當(dāng)使用slot的時(shí)候下邊這個(gè)用法是錯(cuò)誤的
// 錯(cuò)誤示范
<custom-button>
<div> //不能有這一層級
<div class="name_cls" slot="userName">張三</div>
</div>
</custom-button>
shadow root(影子Dom)

瀏覽器提供了一種機(jī)制用于隔離一段代碼和另一段代碼,說到這里你肯定想到iframe,但有時(shí)候iframe會顯得非常的沉重以及隔離了太多,導(dǎo)致我們使用起來非常的麻煩; 我們可以利用shadow root將CSS和HTML綁定在一起封裝成組件,并且其支持天然的樣式隔離;
Element.attachShadow() 方法給指定的元素掛載一個(gè) Shadow DOM,并且返回對 ShadowRoot 的引用。
<script>
class CustomButton extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: "closed" });
const dom = document.querySelector("#test_template").content;
shadow.append(dom);
}
}
customElements.define("custom-button", CustomButton);
</script>
this.attachShadow({ mode: "closed" })的closed表示表示 Shadow DOM 是封閉的,不允許外部訪問。如果mode的值是open,則表示內(nèi)部的節(jié)點(diǎn)可以被外部訪問;
添加樣式
- 如果自定義元素需要樣式,我們可以定義全局的樣式,例如
custom-button{
...
}
- 正常情況我們應(yīng)該將樣式和自定義標(biāo)簽封裝在一起
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div>222</div>
<template id="test_template">
<div class="container">
<span class="test_custom">自測自定義標(biāo)簽</span>
<slot name="userName"></slot>
</div>
<style>
:host {
position: relative;
top: 10px;
}
.test_custom {
color: red;
}
div {
border: 1px solid black;
}
</style>
</template>
<custom-button>
<span slot="userName">張三</span>
</custom-button>
<script>
class CustomButton extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: "closed" });
const dom = document.querySelector("#test_template").content;
shadow.append(dom);
}
}
customElements.define("custom-button", CustomButton);
</script>
</body>
</html>

:host:表示當(dāng)前的自定義元素節(jié)點(diǎn);
另外可以發(fā)現(xiàn)我們定義的div樣式只作用于了影子dom內(nèi)部元素,對于外部的div沒有任何影響,證明了影子Dom的樣式隔離特性;
以上就是Web Components入門教程詳解的詳細(xì)內(nèi)容,更多關(guān)于Web Components入門教程的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
基于JavaScript實(shí)現(xiàn)的折半查找算法示例
這篇文章主要介紹了基于JavaScript實(shí)現(xiàn)的折半查找算法,結(jié)合實(shí)例形式分析了折半查找的原理、操作步驟及javascript實(shí)現(xiàn)折半查找的相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2017-04-04
JavaScript中exec函數(shù)用法實(shí)例分析
這篇文章主要介紹了JavaScript中exec函數(shù)用法,較為詳細(xì)的分析了javascript中exec函數(shù)的功能、定義及使用方法,需要的朋友可以參考下2015-06-06
JavaScript實(shí)現(xiàn)梯形乘法表的方法
這篇文章主要介紹了JavaScript實(shí)現(xiàn)梯形乘法表的方法,涉及基本javascript結(jié)合表格操作的技巧,需要的朋友可以參考下2015-04-04
JS獲取隨機(jī)數(shù)和時(shí)間轉(zhuǎn)換的簡單實(shí)例
下面小編就為大家?guī)硪黄狫S獲取隨機(jī)數(shù)和時(shí)間轉(zhuǎn)換的簡單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-07-07
js style.display=block顯示布局錯(cuò)亂問題的解決方法
下面小編就為大家?guī)硪黄猨s style.display=block顯示布局錯(cuò)亂問題的解決方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-09-09
如何在JavaScript中實(shí)現(xiàn)私有屬性的寫類方式(一)
這篇文章主要介紹了如何在JavaScript中實(shí)現(xiàn)私有屬性的寫類方式。需要的朋友可以過來參考下,希望對大家有所幫助2013-12-12
基于Javascript實(shí)現(xiàn)倒計(jì)時(shí)功能
這篇文章主要為大家詳細(xì)介紹了基于Javascript實(shí)現(xiàn)倒計(jì)時(shí)功能的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-02-02

