摘要:定制元素可以在原生元素外創(chuàng)建定制元素。此定制元素內(nèi)部有一個(gè)加號按鈕,一個(gè)減號按鈕,一個(gè)顯示當(dāng)前值。此主題會在下一部分內(nèi)介紹。定制元素的屬性元素的屬性被稱為,對象內(nèi)的屬性被稱為。做響應(yīng)的同步處理。
Web Components 全攬
Web Components技術(shù)可以把一組相關(guān)的HTML、JS代碼和CSS風(fēng)格打包成為一個(gè)自包含的組件,只要使用大家熟悉的標(biāo)簽即可引入此組件。Web Components技術(shù)包括:
Custom Element
Shadow DOM
Template
HTML Import
四個(gè)分離而又互相關(guān)的四個(gè)構(gòu)造塊。其中核心的即使是Custom Element、Shadow DOM,順便會講到而Template是一個(gè)支持技術(shù)。
HTML Import曾經(jīng)被Chrome加入但是隨后和V0一起被廢棄。這里也不會討論它。
定制元素可以在原生元素外創(chuàng)建定制元素。定制元素是Web組件的一個(gè)基本構(gòu)成塊??梢栽谝粋€(gè)js文件內(nèi)包含Custom Element需要的全部要素,包括HTML模板、CSS Style和ES6類。并使用一個(gè)HTML文件,引用此js文件從而可以使用定制元素。
假設(shè)我們創(chuàng)建Spin Button,定制元素標(biāo)簽為:
我們首先實(shí)現(xiàn)此定制元素,但是為了簡單起見,晚一點(diǎn)才看它的屬性。此定制元素內(nèi)部有一個(gè)加號按鈕,一個(gè)減號按鈕,一個(gè)span顯示當(dāng)前值。那么只需要把這個(gè)HTML模板組織、風(fēng)格和代碼組合在一個(gè)文件內(nèi):
var template = `
1
`
class SpinButton extends HTMLElement{
connectedCallback(){
this.innerHTML = template
var b1 = this.querySelector("[inc]")
var b2 = this.querySelector("[dec]")
var s = this.querySelector("span")
var i = 1
b1.onclick = function(){
s.innerHTML = i++
}
b2.onclick = function(){
s.innerHTML = i--
}
}
}
customElements.define("spin-button",SpinButton)
并且創(chuàng)建一個(gè)index.html文件加載此文件,即可使用新的定制元素spin-button了:
你可以看到執(zhí)行在瀏覽器內(nèi)的界面上的兩個(gè)按鈕和一個(gè)span。創(chuàng)建一個(gè)定制元素有幾個(gè)要點(diǎn):
新的JS定制類需要繼承于類HTMLElement
回調(diào)connectedCallback提供一個(gè)生命周期事件,當(dāng)定制元素成功掛接到DOM后,會調(diào)用此回調(diào),可以在此回調(diào)代碼內(nèi)加入自己的定制內(nèi)容
代碼中的this,指向了此定制元素本身,因此可以通過this.innerHTML設(shè)置本定制元素的內(nèi)部DOM
這樣,我們創(chuàng)建了一個(gè)獨(dú)特的定制元素,這個(gè)元素不在原生的瀏覽器標(biāo)簽內(nèi)。
定制元素就是這樣創(chuàng)建了,并且對于使用者來說,只要通過熟悉的元素標(biāo)簽,即可引用一組帶有定制風(fēng)格、操作和界面的組件了。
但是此時(shí)的定制元素有一個(gè)問題,就是它內(nèi)部定義的風(fēng)格,不僅僅會影響內(nèi)部的元素,也會泄露到外部導(dǎo)致文檔也被影響,從而引發(fā)我們不希望的邊際效應(yīng)。比如在index.html內(nèi)如果在文件尾部加入這樣的文本:
black
你會發(fā)現(xiàn)black文本不是默認(rèn)的顏色,而是紅色,這樣紅色來自于定制元素內(nèi)部的風(fēng)格定義代碼。如果希望隔離組件內(nèi)的風(fēng)格定義,那么可以使用Shaddow DOM技術(shù)。此主題會在下一部分內(nèi)介紹。
Shadow DOMWeb建站使用組件技術(shù)有比較長的歷史了,這個(gè)技術(shù)一直以來都有一個(gè)挑戰(zhàn),就是如何讓一個(gè)頁面可以使用第三方控件,但是不會被此組件使用的CSS風(fēng)格所影響。解決方案是CSS可以局部化。想要組件內(nèi)部的風(fēng)格不會影響到外部,辦法就是使用Shadow DOM。Shadow DOM創(chuàng)建了一個(gè)隔離區(qū),在這個(gè)隔離區(qū)內(nèi)的DOM是獨(dú)立的,這意味著:
內(nèi)部DOM Tree不會被外部文檔訪問到
也不會被外部的風(fēng)格設(shè)置影響
內(nèi)部的風(fēng)格也不會影響到外部文檔
我們拿前一個(gè)案例代碼做實(shí)驗(yàn),看看如果使用這個(gè)技術(shù)特性。
使用Shadow DOM的關(guān)鍵,是首先創(chuàng)建一個(gè)Shadow Node,整個(gè)組件內(nèi)部的HTML片段都插入到此節(jié)點(diǎn)內(nèi),而不是直接使用組件的innerHTML。我們可以在組件對象的構(gòu)造器內(nèi)執(zhí)行此代碼:
class SpinButton extends HTMLElement{ constructor(){ super() var shadow = this.attachShadow({mode:"open"}) var t = document.createElement("template") t.innerHTML = template shadow.appendChild(t.content.cloneNode(true)) } }
執(zhí)行后,你會發(fā)現(xiàn)span的風(fēng)格不再影響組件之外的標(biāo)簽。看起來還是很簡單的,只要把你本來需要構(gòu)造的HTML內(nèi)部DOM插入到shadow節(jié)點(diǎn)內(nèi)即可。
定制元素的屬性元素的屬性被稱為Attribute,JS對象內(nèi)的屬性被稱為Property。代碼慣例上每一個(gè)Attribute都會有JS對象的一個(gè)Property對應(yīng)。為了方便,我們希望添加的Attribute可以和JS內(nèi)的Property同步。就是說,如果有人通過HTML DOM API修改了Attribute,那么我希望對于的JS屬性會被同步修改;反之亦然,有人修改了Property,那么這個(gè)修改可以會同步修改到對應(yīng)的Attribute。
我們以spin-button的value屬性為例。定義一個(gè)普通的Property的方法是通過get/set關(guān)鍵字,比如定義value:
get value(){} set value(newValue){}
隨后就可以使用object.value訪問此屬性值,或者通過object.value = newValue為屬性設(shè)置新值??梢栽趦蓚€(gè)函數(shù)內(nèi)通過代碼設(shè)置和Attribute同步:
get value(){ return this.getAttribute("value") || 1 } set value(v){ this.setAttribute("value",v) }
這樣代碼內(nèi)通過對屬性value的訪問,最后都會導(dǎo)致對Attribute的訪問。如果有代碼對Attribute訪問,如何修改Attribute的同時(shí)同步更新Property呢。這就需要利用HTMLElement提供的生命周期方法了:
static get observedAttributes() { return ["value"]; } attributeChangedCallback(name, oldValue, newValue) { switch (name) { case "value": break; } }
方法observedAttributes聽過返回值聲明需要觀察的屬性,這樣就可以在指定屬性清單發(fā)生更新時(shí)通過另一個(gè)生命周期方法attributeChangedCallback,通知代碼變化的情況。做響應(yīng)的同步處理。整合后的代碼如下:
var template = `
1
`
class SpinButton extends HTMLElement{
constructor(){
super()
var shadow = this.attachShadow({mode:"open"})
var t = document.createElement("template")
t.innerHTML = template
shadow.appendChild(t.content.cloneNode(true))
var b1 = shadow.querySelector("[inc]")
var b2 = shadow.querySelector("[dec]")
this.s = shadow.querySelector("span")
var i = 1
var that = this
b1.onclick = function(){
that.s.innerHTML = ++that.value
}
b2.onclick = function(){
that.s.innerHTML = -- that.value
}
}
static get observedAttributes() {
return ["value"];
}
attributeChangedCallback(name, oldValue, newValue) {
switch (name) {
case "value":
this.s.innerHTML = newValue
break;
}
}
get value(){
return this.getAttribute("value") || 1
}
set value(v){
this.setAttribute("value",v)
}
}
customElements.define("spin-button",SpinButton)
狀態(tài)
Web Components的關(guān)鍵構(gòu)成技術(shù)包括Custom Element和Shadow DOM,最早在Chrome實(shí)現(xiàn),第一個(gè)版本被稱為V0但是其他瀏覽器沒有跟進(jìn),因此逐步被廢棄。本文討論的是V1版本。Firefox也已經(jīng)實(shí)現(xiàn)了V1版本。
可以在網(wǎng)站W(wǎng)hatcaniuse查詢當(dāng)前支持狀態(tài)。
Posts of wb
https://alligator.io/web-comp...
Custom Elements v1: Reusable Web Components
https://developers.google.com...
*3. web-components-examples
https://github.com/mdn/web-co...
Firefox 63 – Tricks and Treats!
https://hacks.mozilla.org/201...
HTML Web Component using Plain JavaScript
https://www.codementor.io/ayu...
6. Doing something with Web Components
https://medium.com/@dalaidunc...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/99639.html
摘要:要求模塊編寫必須在真正的代碼之外套上一層規(guī)定的代碼包裝,樣子看起來是這樣的模塊代碼通過傳遞一個(gè)簽名為的回調(diào)函數(shù)給函數(shù),就可以把需要注入的變量和函數(shù)注入到模塊代碼內(nèi)。 之前寫的文章急速Js全棧教程得到了不錯的閱讀量,霸屏掘金頭條3天,點(diǎn)贊過千,閱讀近萬,甚至還有人在評論區(qū)打廣告,可見也是一個(gè)小小的生態(tài)了;)??磥砗蚃S全棧有關(guān)的內(nèi)容,還是有人頗有興趣的。 showImg(https://...
摘要:最近看了知乎上的一個(gè)話題在工作中,為什么程序員常常瞧不起程序員個(gè)人從業(yè)多年,用過的后端語言,如果你非要讓我說哪種語言好,我會說凡是宏哥說的都是對的,凡是宏哥提倡的都要堅(jiān)持。只有真正的理解了宏哥思想才可以洞穿一切,走出空谷。 最近看了知乎上的一個(gè)話題「在工作中,為什么 Java 程序員常常瞧不起 PHP 程序員?」 個(gè)人從業(yè)多年,用過的后端語言 ASP、ASP.NET、Java、PHP、...
摘要:最近看了知乎上的一個(gè)話題在工作中,為什么程序員常常瞧不起程序員個(gè)人從業(yè)多年,用過的后端語言,如果你非要讓我說哪種語言好,我會說凡是宏哥說的都是對的,凡是宏哥提倡的都要堅(jiān)持。只有真正的理解了宏哥思想才可以洞穿一切,走出空谷。 最近看了知乎上的一個(gè)話題「在工作中,為什么 Java 程序員常常瞧不起 PHP 程序員?」 個(gè)人從業(yè)多年,用過的后端語言 ASP、ASP.NET、Java、PHP、...
摘要:隨著頁面中相同或類似的增加,使得代碼冗余度增加,的重用性問題日益彰顯。影子使得這些與主文檔的保持分離。分離的原因是如果復(fù)雜頁面沒有很好的組織結(jié)構(gòu),樣式容易覆蓋。 為什么 Web Components? 早期在我們構(gòu)建web頁面時(shí),基本上都是通過組合HTML提供的標(biāo)簽來實(shí)現(xiàn)的,再簡單點(diǎn)我們還可以拷貝黏貼bootstrap的css代碼。隨著頁面中相同或類似UI的增加,使得代碼冗余度增加,U...
閱讀 3888·2023-04-26 00:36
閱讀 2685·2021-11-16 11:44
閱讀 1109·2021-11-15 17:58
閱讀 1682·2021-09-30 09:47
閱讀 1225·2019-08-30 13:05
閱讀 1557·2019-08-30 12:55
閱讀 2424·2019-08-30 11:02
閱讀 2756·2019-08-29 17:01