Web?Components入門教程示例詳解
Web Components不兼容IE
2011年提出Web Components,為了解決代碼復(fù)用問題,早于React、Vue;
相對(duì)于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è),我們?cè)趆tml內(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 = "自測(cè)自定義標(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片段,不會(huì)在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">自測(cè)自定義標(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)這種寫法相對(duì)于前一種方式,更加易讀以及便捷
<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">自測(cè)自定義標(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> //不能有這一層級(jí)
<div class="name_cls" slot="userName">張三</div>
</div>
</custom-button>
shadow root(影子Dom)

瀏覽器提供了一種機(jī)制用于隔離一段代碼和另一段代碼,說到這里你肯定想到iframe,但有時(shí)候iframe會(huì)顯得非常的沉重以及隔離了太多,導(dǎo)致我們使用起來非常的麻煩; 我們可以利用shadow root將CSS和HTML綁定在一起封裝成組件,并且其支持天然的樣式隔離;
Element.attachShadow() 方法給指定的元素掛載一個(gè) Shadow DOM,并且返回對(duì) 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">自測(cè)自定義標(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)部元素,對(duì)于外部的div沒有任何影響,證明了影子Dom的樣式隔離特性;
以上就是Web Components入門教程詳解的詳細(xì)內(nèi)容,更多關(guān)于Web Components入門教程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
原生js獲取寬高與jquery獲取寬高的方法關(guān)系對(duì)比
這篇文章主要介紹了原生js獲取寬高與jquery獲取寬高的方法關(guān)系對(duì)比,需要的朋友可以參考下2014-04-04
JavaScript去除數(shù)組里重復(fù)值的方法
這篇文章主要介紹了JavaScript去除數(shù)組里重復(fù)值的方法,涉及javascript針對(duì)數(shù)組操作的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07
基于JavaScript實(shí)現(xiàn)一個(gè)動(dòng)態(tài)脫敏指令
數(shù)據(jù)脫敏是指在不影響數(shù)據(jù)分析結(jié)果的準(zhǔn)確性前提下,對(duì)原始數(shù)據(jù)中的敏感字段進(jìn)行處理,從而降低數(shù)據(jù)敏感度和減少個(gè)人隱私風(fēng)險(xiǎn)的技術(shù)措施,下面我們就來看看如何實(shí)現(xiàn)一個(gè)動(dòng)態(tài)脫敏指令吧2024-12-12
小程序短信驗(yàn)證碼頁面實(shí)現(xiàn)demo
這篇文章主要為大家介紹了小程序短信驗(yàn)證碼頁實(shí)現(xiàn)demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11
前端小知識(shí)之??=?操作符更簡(jiǎn)潔的默認(rèn)值處理方式
這篇文章主要介紹了前端小知識(shí)之??=?操作符更簡(jiǎn)潔的默認(rèn)值處理方式的相關(guān)資料,??=操作符是JavaScript中用于設(shè)置默認(rèn)值的新操作符,它僅在變量值為null或undefined時(shí)才賦值,需要的朋友可以參考下2024-11-11
Ant Design Pro 下實(shí)現(xiàn)文件下載的實(shí)現(xiàn)代碼
這篇文章主要介紹了Ant Design Pro 下實(shí)現(xiàn)文件下載的實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
webpack本地開發(fā)環(huán)境無法用IP訪問的解決方法
下面小編就為大家分享一篇webpack本地開發(fā)環(huán)境無法用IP訪問的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-03-03
JavaScript判斷一個(gè)字符串是否包含指定子字符串的方法
這篇文章主要介紹了JavaScript判斷一個(gè)字符串是否包含指定子字符串的方法,實(shí)例分析了javascript字符串操作的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-03-03

