Web Components應(yīng)用(一)

一忽肛、什么是Web Components?

Web Components是一個(gè)瀏覽器的新功能保屯,它允許開發(fā)者創(chuàng)建可重用的定制元素秉版,該定制元素的功能封裝在代碼之外贤重,定制元素的功能部分由自身的html結(jié)構(gòu)、css樣式以及javascript代碼組成清焕,并且不會干擾到代碼中其他元素并蝗,該元素被定義之后可以在任何web應(yīng)用中使用,使用方式同原生標(biāo)簽元素秸妥。它不依賴于任何框架滚停,可實(shí)現(xiàn)跨框架使用,這也解決了項(xiàng)目重構(gòu)時(shí)換框架即需要重新開發(fā)組件的痛點(diǎn)粥惧。

瀏覽器兼容性可參考:Web Components的瀏覽器兼容性

二键畴、為什么使用Web Components?

相比于其他組件突雪,使用Web Components技術(shù)開發(fā)的組件擁有以下幾個(gè)顯著優(yōu)點(diǎn):

1起惕、一勞永逸

組件擁有更長的壽命,它不需要適應(yīng)新的技術(shù)而重寫咏删。雖然我們團(tuán)隊(duì)目前的主要技術(shù)棧是vue惹想,但是也要考慮到將來項(xiàng)目重構(gòu)時(shí)會面臨技術(shù)棧升級或者更換的一個(gè)情況。

2督函、語法簡單易學(xué)

組件僅由html嘀粱、css激挪、javascript三部分組成,使用它可以不像使用依賴庫或者框架的組件一樣去額外學(xué)習(xí)一些框架的特定語言锋叨。

3垄分、可移植性強(qiáng)

組件可以在任何web應(yīng)用中使用,因?yàn)楹苌偕踔翛]有依賴娃磺,組件的使用障礙要明顯低于依賴庫或者框架的組件锋喜。

但同時(shí),Web Components還存在一些弊端豌鸡,由于目前瀏覽器支持性還不太高,而且官方教程寫的也不是非常清晰易懂段标,使用起來還是有一定難度的涯冠。

由于我們團(tuán)隊(duì)開發(fā)的項(xiàng)目的只需要兼容google瀏覽器,而且團(tuán)隊(duì)技術(shù)棧又比較廣泛逼庞,涉及vue蛇更、react、angluar赛糟,考慮到業(yè)務(wù)組件的可移植性派任,我選擇使用Web components。

三璧南、怎么使用Web Components掌逛?

使用部分的介紹以vue框架下我開發(fā)的一個(gè)業(yè)務(wù)組件為例,該組件主要實(shí)現(xiàn)兩個(gè)功能:1司倚、在瀏覽器展示一段文字豆混;2、所展示的這段文字中的關(guān)鍵字要標(biāo)紅动知。接下來正式進(jìn)入使用步驟的介紹皿伺。

2.1 使用customElements.define()創(chuàng)建一個(gè)自定義元素

window.customElements 是 CustomElementRegistry 的實(shí)例,CustomElementRegistry提供注冊自定義元素和查詢已注冊元素的方法盒粮。

customElements.define()在創(chuàng)建一個(gè)類后定義自定義元素鸵鸥,它接受三個(gè)參數(shù):

  • 第一個(gè)參數(shù)為所創(chuàng)建元素的名稱 (注:為了和原生的元素區(qū)分開,元素的名稱不能是單個(gè)單詞丹皱,且其中必須要有短橫線妒穴,eg: emphasize-words)
  • 第二個(gè)參數(shù)為定義元素行為的類
  • 第三個(gè)參數(shù)為可選參數(shù),是一個(gè)包含extends屬性的配置對象种呐,它指定所創(chuàng)建的元素繼承自哪個(gè)內(nèi)置元素宰翅,可以繼承任何內(nèi)置元素
(function() {
    let target_template = document.createElement("template");
    target_template.setAttribute("id", "emphasizeWordsTemplate");
    //引號內(nèi)填寫的HTML代碼
    target_template.innerHTML = `
        <style>

        </style>

        <span id="words"></span>
    `;
    document.body.append(target_template);
    // 將父組件傳來的純文本變成帶樣式(將關(guān)鍵詞標(biāo)紅)的html
    class EmphasizeWords extends HTMLElement {
        constructor() {
          super();
          var shadow = this.attachShadow( { mode: 'closed' } );
          var templateElem = document.getElementById('emphasizeWordsTemplate');
          var content = templateElem.content.cloneNode(true);
          // 文本
          let text = this.getAttribute('text');
          // 關(guān)鍵詞 
          let keyWords = String(this.getAttribute('keyWords')).split(',');
          // 標(biāo)記顏色
          let color = this.getAttribute('markColor');
          // 將文本中關(guān)鍵詞替換
          for (let i = 0; i < keyWords.length; i++) {
            let r = new RegExp(keyWords[i], "ig");
            if(r.test(text)) {
                text = text.replace(r, `<font color="${color}">${keyWords[i]}</font>`)
            }
          }
          content.getElementById('words').innerHTML = text
          shadow.appendChild(content);
        }
      }
    window.customElements.define('emphasize-words', EmphasizeWords);
})();

2.2 引入自定義元素

Web components有兩種引入方式,以vue框架下引入方式為例:

方法1爽室、在vue的主渲染文件index.html使用script標(biāo)簽將剛剛創(chuàng)建的Web components的js文件引入

<script src="./emphasize-words" defer></script>

方法2汁讼、在vue的入口文件main.js或某個(gè)獨(dú)立vue組件中使用ES module的形式引入

import './emphasize-words'

2.3 使用Web components

Web components通過向?yàn)g覽器注冊自定義元素實(shí)現(xiàn)淆攻,注冊后的自定義元素,使用方法上和原生標(biāo)簽元素相比沒有什么區(qū)別嘿架,你只需要傳入自定義元素要求的屬性即可瓶珊,例如:

<emphasize-words text="關(guān)鍵詞標(biāo)紅" keyWords="關(guān)鍵詞" markColor="red"></emphasize-words>

在vue、react等框架中使用則需要遵守框架特定的語法耸彪,例如在vue中你可以這樣使用它:

<template>
    <div>
        <emphasize-words :text="text" :keyWords="keyWords" markColor="red"></emphasize-words>
    </div>
</template>
<script>

export default {
    data() {
        return {
            text: '文案本意是指放書的桌子伞芹,后來指在桌子上寫字的人。現(xiàn)在指的是公司或企業(yè)中從事文字工作的職位蝉娜,就是以文字來表現(xiàn)已經(jīng)制定的創(chuàng)意策略唱较。文案是一個(gè)與廣告創(chuàng)意先后相繼呈現(xiàn)的表現(xiàn)過程、發(fā)展過程與深化過程召川, 多存在于廣告公司南缓,企業(yè)宣傳與新聞策劃工作等。',
            keyWords: ['文案', '新聞策劃', '廣告'],
        }
    },
}
</script>

2.4 用生命周期解決自定義元素使用時(shí)報(bào)錯(cuò)問題

如上2.1的示例可能會產(chǎn)生一個(gè)問題——若這個(gè)組件還未加載完就被調(diào)用荧呐,會導(dǎo)致組件報(bào)錯(cuò)汉形。這時(shí),就要用到生命周期函數(shù)倍阐。

在custom element的構(gòu)造函數(shù)中概疆,可以指定多個(gè)不同的回調(diào)函數(shù),它們將會在元素的不同生命時(shí)期被調(diào)用:

  • connectedCallback:當(dāng) custom element首次被插入文檔DOM時(shí)峰搪,被調(diào)用岔冀。

  • disconnectedCallback:當(dāng) custom element從文檔DOM中刪除時(shí),被調(diào)用罢艾。

  • adoptedCallback:當(dāng) custom element被移動到新的文檔時(shí)楣颠,被調(diào)用。

  • attributeChangedCallback: 當(dāng) custom element增加咐蚯、刪除童漩、修改自身屬性時(shí),被調(diào)用春锋。

將上述功能代碼的調(diào)用位置稍作修改即可(等組件加載完畢再執(zhí)行功能代碼)

let target_template = document.createElement("template");
  target_template.setAttribute("id", "emphasizeWordsTemplate");
  //引號內(nèi)填寫的HTML代碼
  target_template.innerHTML = `
  <style>

    </style>

  <span id="words"></span>
  `; 
  document.body.append(target_template);

  class EmphasizeWords extends HTMLElement {
      constructor() {
        super();
      }
      init(){
        let shadow = this.attachShadow( { mode: 'open' } );
        let templateElem = document.getElementById('emphasizeWordsTemplate');
        let content = templateElem.content.cloneNode(true);
        // 將父組件傳來的文本變成帶樣式的的html
        console.log(this, this.getAttribute('text'));
        // 文本
        let text = this.getAttribute('text'); 
        console.log(text);
        // 關(guān)鍵詞
        let keyWords = String(this.getAttribute('keyWords')).split(',');
        // 標(biāo)記顏色
        let color = this.getAttribute('markColor');
        // 將文本中關(guān)鍵詞替換
        for (let i = 0; i < keyWords.length; i++) {
          let r = new RegExp(keyWords[i], "ig");
          if(r.test(text)) {
              text = text?.replace(r, `<font color="${color}">${keyWords[i]}</font>`)
          }
        }
        content.getElementById('words').innerHTML = text
        shadow.appendChild(content);
      }
      connectedCallback() {
        console.log('被加載')
        this.init();
      }
      disconnectedCallback() {
        console.log('被刪除')
      }
      adoptedCallback() {
        console.log('被移動到新的文檔')
      }
      attributeChangedCallback() {
        console.log('增加矫膨、刪除、修改自身屬性')
      }
    }
    window.customElements.define('emphasize-words', EmphasizeWords);

四期奔、展示結(jié)果

瀏覽器展示結(jié)果:

image

控制臺打印傳值后的emphasize-words標(biāo)簽及其text屬性內(nèi)容:

image

五侧馅、總結(jié)

Web components 的出現(xiàn)讓組件可以快速適應(yīng)變化,讓組件擁有更長的壽命呐萌,但其瀏覽器的支持性不高的缺點(diǎn)也使它目前沒有成為主流的選擇馁痴。本篇文章只簡單介紹了Web components在vue項(xiàng)目中的使用,關(guān)于Web components的知識點(diǎn)還有非常多肺孤,比如插槽的使用罗晕、現(xiàn)有的Web components庫等济欢,之后也會根據(jù)使用和調(diào)研情況慢慢完善該系列文章。

六小渊、參考材料

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末法褥,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子酬屉,更是在濱河造成了極大的恐慌半等,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件呐萨,死亡現(xiàn)場離奇詭異杀饵,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)谬擦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進(jìn)店門凹髓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人怯屉,你說我怎么就攤上這事《祝” “怎么了锨络?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長狼牺。 經(jīng)常有香客問我羡儿,道長,這世上最難降的妖魔是什么是钥? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任掠归,我火速辦了婚禮,結(jié)果婚禮上悄泥,老公的妹妹穿的比我還像新娘虏冻。我一直安慰自己,他們只是感情好弹囚,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布厨相。 她就那樣靜靜地躺著,像睡著了一般鸥鹉。 火紅的嫁衣襯著肌膚如雪蛮穿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天毁渗,我揣著相機(jī)與錄音践磅,去河邊找鬼。 笑死灸异,一個(gè)胖子當(dāng)著我的面吹牛府适,可吹牛的內(nèi)容都是我干的羔飞。 我是一名探鬼主播,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼细溅,長吁一口氣:“原來是場噩夢啊……” “哼褥傍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起喇聊,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤恍风,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后誓篱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體朋贬,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年窜骄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了锦募。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,809評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡邻遏,死狀恐怖糠亩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情准验,我是刑警寧澤赎线,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站糊饱,受9級特大地震影響垂寥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜另锋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一滞项、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧夭坪,春花似錦文判、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至竞惋,卻和暖如春柜去,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拆宛。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工嗓奢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人浑厚。 一個(gè)月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓股耽,卻偏偏與公主長得像根盒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子物蝙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容

  • 前言:這周完成了兩場技術(shù)分享會炎滞,下周還有一場,就完成了這階段的一個(gè)重大任務(wù)诬乞。分享會是關(guān)于 TS 的册赛,我這兩場分享會...
    CondorHero閱讀 980評論 0 2
  • 前端組件化其實(shí)是個(gè)持續(xù)了很長時(shí)間的過程了,從最開始的jquery的插件開始震嫉。我們就在封裝一些js森瘪,css,html...
    潘逸飛閱讀 9,784評論 1 16
  • 看到這個(gè)標(biāo)題可能有的小伙伴想到的是React 票堵、Vue 或者 Angular 的自定義組件扼睬,no no no! W...
    滿是裂縫的花卷閱讀 713評論 0 1
  • 前言 不知不覺悴势,2019年即將接近尾聲窗宇,現(xiàn)有前端三大框架也各自建立著自己的生態(tài)、自己的使用群體特纤。從angular1...
    Kaku_fe閱讀 2,761評論 0 19
  • 定義 瀏覽器原生支持的一套組件封裝技術(shù)担映。這里有兩個(gè)關(guān)鍵字: 組件技術(shù) 瀏覽器原生 組件化一直是前端完善的方向,從早...
    cd2001cjm閱讀 696評論 0 0