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

使用 window.customElements.define 自定義html標簽元素,自定義元素需要我們用JS封裝一個,我們在html內(nèi)使用的自定義元素custom-button就是該類的實例;
自定義標簽的生命周期 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 = "自測自定義標簽";
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)容添加到當前自定義標簽內(nèi),this表示自定義元素實例
HTML模板(template、slot)

<template>:包含一個html片段,不會在html初始化時渲染。主要作用是:通過JavaScript獲取該代碼片段將其放入自定義標簽內(nèi)顯示,主要作用于自定義標簽
<!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">自測自定義標簽</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>插槽:給模板元素傳值,增強模板元素的靈活性和通用性。 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">自測自定義標簽</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é)點內(nèi),主要是因為我們的slot沒有用在影子dom種,所以瀏覽器將<div class="name_cls">張三</div>當成其正常的元素進行渲染了;
<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>

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

瀏覽器提供了一種機制用于隔離一段代碼和另一段代碼,說到這里你肯定想到iframe,但有時候iframe會顯得非常的沉重以及隔離了太多,導(dǎo)致我們使用起來非常的麻煩; 我們可以利用shadow root將CSS和HTML綁定在一起封裝成組件,并且其支持天然的樣式隔離;
Element.attachShadow() 方法給指定的元素掛載一個 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é)點可以被外部訪問;
添加樣式
- 如果自定義元素需要樣式,我們可以定義全局的樣式,例如
custom-button{
...
}
- 正常情況我們應(yīng)該將樣式和自定義標簽封裝在一起
<!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">自測自定義標簽</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:表示當前的自定義元素節(jié)點;
另外可以發(fā)現(xiàn)我們定義的div樣式只作用于了影子dom內(nèi)部元素,對于外部的div沒有任何影響,證明了影子Dom的樣式隔離特性;
以上就是Web Components入門教程詳解的詳細內(nèi)容,更多關(guān)于Web Components入門教程的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
js style.display=block顯示布局錯亂問題的解決方法
下面小編就為大家?guī)硪黄猨s style.display=block顯示布局錯亂問題的解決方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-09-09
如何在JavaScript中實現(xiàn)私有屬性的寫類方式(一)
這篇文章主要介紹了如何在JavaScript中實現(xiàn)私有屬性的寫類方式。需要的朋友可以過來參考下,希望對大家有所幫助2013-12-12

