成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

WebComponent魔法堂:深究Custom Element 之 面向痛點(diǎn)編程

flyer_dev / 2269人閱讀

摘要:前言最近加入到新項(xiàng)目組負(fù)責(zé)前端技術(shù)預(yù)研和選型,一直偏向于以為代表的技術(shù)線,于是查閱各類資料想說服老大向這方面靠,最后得到的結(jié)果是資料是英語(yǔ)無所謂,最重要是上符合要求,技術(shù)的事你說了算。但當(dāng)我們需要?jiǎng)討B(tài)實(shí)例化元素時(shí),命令式則是最佳的選擇。

前言

?最近加入到新項(xiàng)目組負(fù)責(zé)前端技術(shù)預(yù)研和選型,一直偏向于以Polymer為代表的WebComponent技術(shù)線,于是查閱各類資料想說服老大向這方面靠,最后得到的結(jié)果是:"資料99%是英語(yǔ)無所謂,最重要是UI/UX上符合要求,技術(shù)的事你說了算。",于是我只好乖乖地去學(xué)UI/UX設(shè)計(jì)的事,木有設(shè)計(jì)師撐腰的前端是苦逼的:(嘈吐一地后,還是擠點(diǎn)時(shí)間總結(jié)一下WebComponent的內(nèi)容吧,為以后作培訓(xùn)材料作點(diǎn)準(zhǔn)備。

浮在水面上的痛 組件噪音太多了!

?在使用Bootstrap的Modal組件時(shí),我們不免要Ctrl+c然后Ctrl+v下面一堆代碼


?一個(gè)不留神誤刪了一個(gè)結(jié)束標(biāo)簽,或拼錯(cuò)了某個(gè)class或?qū)傩阅蔷捅吡耍藭r(shí)一個(gè)語(yǔ)法高亮、提供語(yǔ)法檢查的編輯器是如此重要?。〉俏移鋵?shí)只想配置個(gè)Modal而已。
?由于元素信息由標(biāo)簽標(biāo)識(shí)符,元素特性樹層級(jí)結(jié)構(gòu)組成,所以排除噪音后提取的核心配置信息應(yīng)該如下(YAML語(yǔ)法描述):

dialog:
  modal: true
  children:  
    header: 
      title: Modal title
      closable: true
    body:
      children:
        p:
          textContent: One fine body…
    footer
      children:
        button: 
          type: close
          textContent: Close
        button: 
          type: submit 
          textContent: Save changes

轉(zhuǎn)換成HTML就是


  
  
    

One fine body…

Close Save changes

而像Alert甚至可以極致到這樣

是不是很簡(jiǎn)單?。?/alert>

可惜瀏覽器木有提供,那怎么辦呢?

手打牛丸模式1

既然瀏覽器木有提供,那我們自己手寫一個(gè)吧!

復(fù)盤找問題

?雖然表面上實(shí)現(xiàn)了需求,但存在2個(gè)明顯的缺陷

不完整的元素實(shí)例化方式
原生元素有2種實(shí)例化方式

聲明式


命令式

// 元素實(shí)例化
const input = new HTMLInputElement() // 或者 document.createElement("INPUT")
input.type = "text"
// 添加到DOM樹
document.querySelector("#mount-node").appendChild(input)

?由于聲明式注重What to do,而命令式注重How to do,并且我們操作的是DOM,所以采用聲明式的HTML標(biāo)簽比命令式的JavaScript會(huì)來得簡(jiǎn)潔平滑。但當(dāng)我們需要?jiǎng)討B(tài)實(shí)例化元素時(shí),命令式則是最佳的選擇。于是我們勉強(qiáng)可以這樣

// 元素實(shí)例化
const myAlert = new Alert()
// 添加到DOM樹
document.querySelector("#mount-node").appendChild(myAlert.el)
/*
由于Alert無法正常實(shí)現(xiàn)HTMLElement和Node接口,因此無法實(shí)現(xiàn)
document.querySelector("#mount-node").appendChild(myAlert)
myAlert和myAlert.el的差別在于前者的myAlert是元素本身,而后者則是元素句柄,其實(shí)沒有明確哪種更好,只是原生方法都是支持操作元素本身,一下來個(gè)不一致的句柄不蒙才怪了
*/

?即使你能忍受上述的代碼,那通過innerHTML實(shí)現(xiàn)半聲明式的動(dòng)態(tài)元素實(shí)例化,那又怎么玩呢?是再手動(dòng)調(diào)用一下registerElement("alert", el => new Alert(el))嗎?
?更別想通過document.createElement來創(chuàng)建自定義元素了。

有生命無周期
?元素的生命從實(shí)例化那刻開始,然后經(jīng)歷如添加到DOM樹、從DOM樹移除等階段,而想要更全面有效地管理元素的話,那么捕獲各階段并完成相應(yīng)的處理則是唯一有效的途徑了。

生命周期很重要

?當(dāng)定義一個(gè)新元素時(shí),有3件事件是必須考慮的:

元素自閉合: 元素自身信息的自包含,并且不受外部上下文環(huán)境的影響;

元素的生命周期: 通過監(jiān)控元素的生命周期,從而實(shí)現(xiàn)不同階段完成不同任務(wù)的目錄;

元素間的數(shù)據(jù)交換: 采用property in, event out的方式與外部上下文環(huán)境通信,從而與其他元素進(jìn)行通信。
?元素自閉合貌似無望了,下面我們?cè)囋嚤O(jiān)聽元素的生命周期吧!

手打牛丸模式2

?通過constructor我們能監(jiān)聽元素的創(chuàng)建階段,但后續(xù)的各個(gè)階段呢?可幸的是可以通過MutationObserver監(jiān)聽document.body來實(shí)現(xiàn):)
最終得到的如下版本:

"use strict"
class Alert{
  constructor(el = document.createElement("ALERT")){
    this.el = el
    this.el.fireConnected = () => { this.connectedCallback && this.connectedCallback() }
    this.el.fireDisconnected = () => { this.disconnectedCallback && this.disconnectedCallback() }
    this.el.fireAttributeChanged = (attrName, oldVal, newVal) => { this.attributeChangedCallback && this.attributeChangedCallback(attrName, oldVal, newVal) } 

    const raw = el.innerHTML
    el.dataset.resolved = ""
    el.innerHTML = `
${raw}
` el.querySelector("button.close").addEventListener("click", _ => this.close()) } close(){ this.el.style.display = "none" } show(){ this.el.style.display = "block" } connectedCallback(){ console.log("connectedCallback") } disconnectedCallback(){ console.log("disconnectedCallback") } attributeChangedCallback(attrName, oldVal, newVal){ console.log("attributeChangedCallback") } } function registerElement(tagName, ctorFactory){ [...document.querySelectorAll(`${tagName}:not([data-resolved])`)].forEach(ctorFactory) } function registerElements(ctorFactories){ for(let k in ctorFactories){ registerElement(k, ctorFactories[k]) } } const observer = new MutationObserver(records => { records.forEach(record => { if (record.addedNodes.length && record.target.hasAttribute("data-resolved")){ // connected record.target.fireConnected() } else if (record.removedNodes.length){ // disconnected const node = [...record.removedNodes].find(node => node.hasAttribute("data-resolved")) node && node.fireDisconnected() } else if ("attributes" === record.type && record.target.hasAttribute("data-resolved")){ // attribute changed record.target.fireAttributeChanged(record.attributeName, record.oldValue, record.target.getAttribute(record.attributeName)) } }) }) observer.observe(document.body, {attributes: true, childList: true, subtree: true}) registerElement("alert", el => new Alert(el))
總結(jié)

?千辛萬苦擼了個(gè)基本不可用的自定義元素模式,但通過代碼我們進(jìn)一步了解到對(duì)于自定義元素我們需要以下基本特性:

自定義元素可通過原有的方式實(shí)例化(,new CustomElement()document.createElement("CUSTOM-ELEMENT"))

可通過原有的方法操作自定義元素實(shí)例(如document.body.appendChild等)

能監(jiān)聽元素的生命周期
下一篇《WebComponent魔法堂:深究Custom Element 之 標(biāo)準(zhǔn)構(gòu)建》中,我們將一同探究H5標(biāo)準(zhǔn)中Custom Element API,并利用它來實(shí)現(xiàn)滿足上述特性的自定義元素:)

?尊重原創(chuàng),轉(zhuǎn)載請(qǐng)注明來自: http://www.cnblogs.com/fsjohn... ^_^肥仔John

感謝

Custom ELement
Custom ELement v1
MutationObserver

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/80535.html

相關(guān)文章

  • WebComponent魔法:深究Custom Element 標(biāo)準(zhǔn)構(gòu)建

    摘要:明確各階段適合的操作用于初始化元素的狀態(tài)和設(shè)置事件監(jiān)聽,或者創(chuàng)建。事件類型轉(zhuǎn)換通過捕獲事件,然后通過發(fā)起事件來對(duì)事件類型進(jìn)行轉(zhuǎn)換,從而觸發(fā)更符合元素特征的事件類型。 前言 ?通過《WebComponent魔法堂:深究Custom Element 之 面向痛點(diǎn)編程》,我們明白到其實(shí)Custom Element并不是什么新東西,我們甚至可以在IE5.5上定義自己的alert元素。但這種簡(jiǎn)單...

    philadelphia 評(píng)論0 收藏0
  • JS魔法深究JS異步編程模型

    摘要:而同步和異步則是描述另一個(gè)方面。異步將數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間的操作由系統(tǒng)自動(dòng)處理,然后通知應(yīng)用程序直接使用數(shù)據(jù)即可。 前言 ?上周5在公司作了關(guān)于JS異步編程模型的技術(shù)分享,可能是內(nèi)容太干的緣故吧,最后從大家的表情看出這條粉腸到底在說啥?的結(jié)果:(下面是PPT的講義,具體的PPT和示例代碼在https://github.com/fsjohnhuan...上,有興趣就上去看看吧! ...

    idealcn 評(píng)論0 收藏0
  • CSS魔法:小結(jié)一下Box Model與Positioning Scheme

    摘要:魔法堂重新認(rèn)識(shí)和魔法堂你一定誤解過的魔法堂就這個(gè)樣魔法堂說說那個(gè)被埋沒的志向深入細(xì)節(jié)后會(huì)發(fā)現(xiàn)中定位模式之間,和之間存在千絲萬縷的關(guān)系,必須以俯瞰的角度捋一下。當(dāng)采用時(shí),屬性的實(shí)際值會(huì)被重置為。由于和則需要通過來引入來提供盒子定位微調(diào)的功能。 前言 ?對(duì)于Box Model和Positioning Scheme中3種定位模式的細(xì)節(jié),已經(jīng)通過以下幾篇文章記錄了我對(duì)其的理解和思考。?《CSS...

    szysky 評(píng)論0 收藏0
  • CSS魔法:你真的理解z-index嗎?

    摘要:與的映射關(guān)系為。與根對(duì)應(yīng)的對(duì)應(yīng)的層疊上下文,是其他的祖先,的范圍覆蓋整條。注意的默認(rèn)值為,自動(dòng)賦值為。對(duì)于,它會(huì)將賦予給對(duì)應(yīng)的,而則不會(huì)。 一、前言                               ?假如只是開發(fā)簡(jiǎn)單的彈窗效果,懂得通過z-index來調(diào)整元素間的層疊關(guān)系就夠了。但要將多個(gè)彈窗間層疊關(guān)系給處理好,那么充分理解z-index背后的原理及兼容性問題就是必要的知識(shí)...

    andycall 評(píng)論0 收藏0
  • CSS魔法:display:none與visibility:hidden的恩怨情仇

    摘要:不耽誤表單提交數(shù)據(jù)雖然我們無法看到的元素,但當(dāng)表單提交時(shí)依然會(huì)將隱藏的元素的值提交上去。讓元素在見面上不可視,但保留元素原來占有的位置。不過由于各瀏覽器實(shí)現(xiàn)效果均有出入,因此一般不會(huì)使用這個(gè)值。繼承父元素的值。 前言 ?還記得面試時(shí)被問起請(qǐng)說說display:none和visibility:hidden的區(qū)別嗎?是不是回答完display:none不占用原來的位置,而visibilit...

    selfimpr 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<