在現在前端元件化開發大行其道的今天,各種Framework讓人眼花繚亂,同一個公司,不同團隊,可能使用的是不同的框架。那麼在統一視覺,互動,功能上,不同的框架可以都需要用不同的框架開發一遍,但是在功能和互動有所改變的時候,又需要全部同步開發一次。這種對人力和物力都是一種消耗,而且維護性也不是很好,那麼有沒有一種元件可以相容所有的框架,並且開發和維護方便呢?那麼Web Components可能就是你需要的答案。
Web Components是原生提供的一種技術,他允許建立可重用的定製元素。
概念
Web Components 是原生提供的一種技術,可以自定義UI控制元件。Web Components由四項技術組成。
- Custom elements(自定義元素)
- Shadow DOM(影子DOM)
- HTML templates(HTML模板)
- HTML Imports(HTML匯入)
- Custom elements
一組javascript API,允許你定義custom element及其行為。
customElements.define(`jason-custom`,
class extends HTMLElement {
constructor() {
super()
let jasonTestElem = document.createElement(`div`);
jasonTestElem.textContent = this.getAttribute(`text`);
let shadowRoot = this.attachShadow({mode: `open`})
.appendChild(jasonTestElem)
}
})
複製程式碼
使用CustomElementRegistry物件來生成custom elements,該物件允許你註冊一個custom element
customElements.define()
接受三個引數:
- DOMString 建立元素的名稱(custom element名稱中必須包含短橫線);
- 類物件 定於類的行為;
- 一個包含extends屬性的物件,可選引數,指定建立的元素繼承自哪個內建元素。
custom elment共有兩種:
- Autonomous custom elements
是一種獨立元素,他不繼承任何一種HTML元素,你可以在頁面中直接使用它,比如<jason-elm></jason-elm>
, 或者document.createElement(`jason-elm`)
- Customized built-in elements 繼承基本的HTML元素,建立時,你必須要繼承自某個基本的HTML元素,使用的時候需在基本元素中通過
is
屬性指定名稱。比如<p is=`jason-elm`></p>
, 或者document.createElement(`p`, { is: `jason-elm`})
例子:
Autonomous custom elements
class JasonCustom extends HTMLElement {
constructor() {
super()
let divElem = document.createElement(`div`)
divElem.textContent = `This is a test Autonomous custom element`
let shadowRoot = this.attachShadow({mode: `open`})
shadowRoot.appendChild(divElem)
}
}
customElements.define(`jason-custom`, JasonCustom)
複製程式碼
那麼我們就可以在頁面中使用他了<jason-custom />
Customized built-in elements
class JasonCustom extends HTMLUListElement {
construtor() {
super()
//
}
}
customElements.define(`jason-custom`, JasonCustom, { extends: `ul` })
複製程式碼
在頁面中使用這種自定義的元素使用
<ul is=`jason-custom` />
自定義元件的生命週期回撥函式
- connectedCallback: 當custom element 首次被插入文件DOM時,被呼叫。
- disconnectedCallback: 當 custom element從文件DOM中刪除時,被呼叫。
- adoptedCallback: 當 custom element被移動到新的文件時,被呼叫。
- attributesChangedCallback: 當 custom element增加、刪除、修改自身屬性時,被呼叫。
使用宣告週期回撥函式的例子可以線上看life-cycle-callbacks
Shadow DOM
Web components 一個重要特性就是封裝,他可以將HTML, CSS,和行為隱藏起來,並從頁面上的其他程式碼分開起來,這樣不用的功能就不會混在一起。那麼就是要介紹的Shadow DOM, shadow DOM可以將隱藏的獨立的元素新增到一個元素上。
Shadow DOM允許將隱藏的DOM新增到常規的DOM樹中
Shadow DOM 有幾個概念
- Shadow host: 一個常規 DOM節點,Shadow DOM會被新增到這個節點上。
- Shadow tree:Shadow DOM內部的DOM樹。
- Shadow boundary:Shadow DOM結束的地方,也是常規 DOM開始的地方。
- Shadow root: Shadow tree的根節點。
你可以像操作基本的DOM元素一樣操作Shadow DOM元素,你也可以給Shadow DOM新增<style>
而且隻影響Shadow DOM裡的元素。Shadow DOM的標準意味著你可以為自己的元素維護一組Shadow DOM。
用法
可以使用Element.attachShadow()
來為任意一個元素新增Shoadow DOM,attachShadow裡接受一個物件作為引數,引數有個屬性mode
,有兩個可選值open
close
。
let shadowOpen = Elementp.attachShadow({`mode`: open})
let shadowClose = Elementp.attachShadow({`mode`: close})
複製程式碼
open
可以通過javascript來獲取shandow DOM 例如
let shadowDom = Elementp.shadowRoot
複製程式碼
close
的話,就是不可以在外部獲取到shadow Dom 了,訪問shadowRoot
就會返回null
更具體的文章請檢視
Open vs. Closed Shadow DOM(有可能需要科學上網)
templates
slot
對的,沒有錯,現在原生提供了模板的功能!!這種模板不會被瀏覽器渲染但是可以使用javascript呼叫!
官方例子
<template id="my-paragraph">
<p>My paragraph</p>
</template>
複製程式碼
使用的時候怎麼用呢
let template = document.getElementById(`my-paragraph`);
let templateContent = template.content;
document.body.appendChild(templateContent);
複製程式碼
你可以用slot 增加template的靈活度,slot的作用是用來提供一個佔位的
slot使用 name 屬性作為id, 你能在tempalte 中定義任意的 html 片斷作為佔位符,在模板物件被使用在html 指令碼中時。
例如:
// tamplate
<p><slot name="my-text">My default text</slot></p>
// 使用時
<my-paragraph>
<span slot="my-text">Let`s have some different text!</span>
</my-paragraph>
//生成的html
<p><span>Let`s have some different text!</span></p>
複製程式碼
當然上面這些程式碼都算是農耕時代的程式碼,那麼可以讓我們用工業2.0的效率來開發web Components 元件的框架有Google的polymer,ionic 自己的stencil。
雖然這個標準好久就出現了,但是其實一直沒有很多的開發者介入。可能源於這玩意的相容性。
可以看到除了chrome高版本和safari是支援最完全的。但是這玩意多好玩的啊,可以拿來做實驗性的產品來玩玩多好!