Web Components使用(一)

在使用Web Components之前,我們先看看上一篇文章Web Components簡介,其中提到了相關(guān)的接口、屬性和方法。
正是這些接口、屬性和方法才實現(xiàn)了Web Components的主要技術(shù):Custom elements(自定義元素)、Shadow DOM(影子DOM)、HTML templates(HTML模板)。
由于并不是所有的接口以及接口所包含的方法都會被用到,所以我們從實際的案例出發(fā),逐步了解Web Components的使用。

需求1:創(chuàng)建一個基礎(chǔ)的組件,包含一個輸入框,和一個button。

mian.js

class SearchInput extends HTMLElement {
    constructor() {
        super();
        // 創(chuàng)建一個 shadow root
        let shadow = this.attachShadow({mode: 'open'});

        const input = document.createElement('input');
        input.setAttribute('type', 'text');
        input.setAttribute('class', 'input-vlaue');

        const button = document.createElement('input');
        button.setAttribute('type', 'button');
        button.setAttribute('value', 'Search');

        // 創(chuàng)建一些 CSS,并應(yīng)用到 shadow dom上
        let style = document.createElement('style');
        style.textContent=".input-vlaue{margin:5px; color:red;}";


        shadow.append(input);
        shadow.append(button);
        shadow.append(style);
    }
}

// declare var customElements: CustomElementRegistry;
customElements.define('search-input', SearchInput);

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./main.js"></script>
</head>
<body>
    <search-input></search-input>
    <search-input></search-input>
    <search-input></search-input>
</body>
</html>
運行結(jié)果

這樣子,一個input + button的組件就實現(xiàn)了。這里用到的技術(shù)有Custom elements(自定義元素)、Shadow DOM(影子DOM)。

使用Shadow DOM的好處:Shadow DOM 內(nèi)部的元素始終不會影響到它外部的元素

要注意的是,不是每一種類型的元素都可以附加到shadow root(影子根)下面。出于安全考慮,一些元素不能使用 shadow DOM(例如<a>),以及許多其他的元素。

Element.attachShadow() 方法給指定的元素掛載一個Shadow DOM,并且返回對 ShadowRoot 的引用。具體方法:創(chuàng)建一個ShadowRoot并返回它:

attachShadow(init: ShadowRootInit): ShadowRoot;

attachShadow()的參數(shù)是一個對象,里面包含兩個屬性,mode和delegatesFocus。

mode:可以是open/closed。
  • open:shadow root元素可以從js外部訪問根節(jié)點
  • closed:拒絕從js外部訪問關(guān)閉的shadow root節(jié)點
delegatesFocus 焦點委托

一個布爾值, 當(dāng)設(shè)置為 true 時, 指定減輕自定義元素的聚焦性能問題行為.
當(dāng)shadow DOM中不可聚焦的部分被點擊時, 讓第一個可聚焦的部分成為焦點, 并且shadow host(影子主機)將提供所有可用的 :focus 樣式.

使用Custom elements(自定義元素)的好處:語義化,簡單明了。
customElements.define('search-input', SearchInput)實現(xiàn)了CustomElementRegistry接口,無返回值:
interface CustomElementRegistry {
    define(name: string, constructor: CustomElementConstructor, options?: ElementDefinitionOptions): void;
    get(name: string): any;
    upgrade(root: Node): void;
    whenDefined(name: string): Promise<void>;
}
需求2:可是真正的組件不僅僅有顯示的功能,還需要綁定一些事件,例如上面的例子,點擊了如何觸發(fā)search事件呢?
核心:element.addEventListener()

代碼示例(index.html不變):

class SearchInput extends HTMLElement {
    constructor() {
        super();
        // 創(chuàng)建一個 shadow root
        let shadow = this.attachShadow({mode: 'open'});

        const input = document.createElement('input');
        input.setAttribute('type', 'text');
        input.setAttribute('class', 'input-vlaue');

        const button = document.createElement('input');
        button.setAttribute('type', 'button');
        button.setAttribute('value', 'Search');

        const text = document.createElement('p');

        // 創(chuàng)建一些 CSS,并應(yīng)用到 shadow dom上
        let style = document.createElement('style');
        style.textContent=".input-vlaue{margin:5px; color:red;}";

        shadow.append(input);
        shadow.append(button);
        shadow.append(text);
        shadow.append(style);

        button.addEventListener('click', e => {
            text.textContent = '按鈕被點擊了~'
        });
    }
}

// declare var customElements: CustomElementRegistry;
customElements.define('search-input', SearchInput);
需求3:我們知道,像react、vue都有組件自身的狀態(tài)管理,和利用Props進行數(shù)據(jù)傳遞,那么,在web components中是怎么實現(xiàn)的呢?
核心:this.getAttribute(props),class內(nèi)部屬性,生命周期

main.js

class SearchInput extends HTMLElement {
    constructor() {
        super();
        this.state = { count:0 };
        // 創(chuàng)建一個 shadow root
        let shadow = this.attachShadow({mode: 'open'});

        const input = document.createElement('input');
        input.setAttribute('type', 'text');
        input.setAttribute('class', 'input-value');

        const button = document.createElement('input');
        button.setAttribute('type', 'button');
        button.setAttribute('value', 'Search');

        const text = document.createElement('p');

        // 創(chuàng)建一些 CSS,并應(yīng)用到 shadow dom上
        let style = document.createElement('style');
        style.textContent=".input-vlaue{margin:5px; color:red;}";

        shadow.append(input);
        shadow.append(button);
        shadow.append(text);
        shadow.append(style);

        button.addEventListener('click', e => {
            this.state.count++;
            text.textContent = `按鈕被點擊了${this.state.count}次。`
        });
    }

    connectedCallback () {
        const defaultValue = this.getAttribute('defaultValue');
        const input = this.shadowRoot.querySelector('.input-value');
        input.value = defaultValue;
    }
}

// declare var customElements: CustomElementRegistry;
customElements.define('search-input', SearchInput);

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./main.js"></script>
</head>
<body>
    <search-input defaultValue="input1"></search-input>
    <search-input defaultValue="input2"></search-input>
    <search-input defaultValue="input3"></search-input>
</body>
</html>
運行結(jié)果
到此,我們已經(jīng)了解了利用Web Components創(chuàng)建一個組件,如何觸發(fā)組件的事件,如何利用props向組件內(nèi)部傳遞數(shù)據(jù)以及組件內(nèi)部的狀態(tài)管理。

目前來看缺乏的就是組件間的通信了,目前還沒發(fā)現(xiàn)有類似react、vue的組件間通信的方法,不過我們可以利用localStorage,StorageEvent間接的發(fā)生組件間的通信、界面渲染。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容