iT邦幫忙

2022 iThome 鐵人賽

DAY 14
0

小弟我查的資料不多,對於未來web component可能會出現的新技術只有查到Declarative Shadow DOM。

SSR使用web component的未來解法 - Declarative Shadow DOM

SPA技術很好用,因為用Javascript來建構頁面時,開發和使用者互動的功能很簡單。可是因為SPA是完全由javascript生成頁面,對SEO非常不友好,所謂的Isomorphic JavaScript技術也相應而生。而web component也因為是使用javascript來建構custom element和shadow DOM,基本上SPA會有的問題web component都會有,所以在SEO的問題上,也可以使用相同的思路來處理。

Isomorphic JavaScript的核心我認為有二部分,第一部分是在伺服端就做出HTML,第二部分則是在前端載入JS後的hydration(注水)。

Declarative Shadow DOM現在只能在Chrome系列的瀏覧器上使用,其他瀏覧器不會生成DOM

Can i use 支援表 https://caniuse.com/declarative-shadow-dom

HTML的部分 - template元素的shadowroot屬性

shadowroot這個屬性可以告訴瀏覧器,template元素和內容在生成DOM時是要渲染成Shadow DOM;當然,對那些不支援shadowroot屬性的瀏覧器來說,template元素還是會跳過不渲染。

shadowroot="open"就像是使用this.attachShadow({mode: 'open'})一樣

<my-com id="my-com" card-content="ha! you~" content-color="yellow">
    <template shadowroot="open">
        <style>
            ...
        </style>
        <div class='card'>
            <h2 id='card-title' class='card-title'>title</h2>
            <div id='card-content' class='card-content'>content</div>
            <slot id='card-slot'></slot>
            <div id='card-content2' class='card-content2'>content2</div>
        </div>
    </template>
    <div id="slot">click</div>
</my-com>

Javascript的部分-hydration

如果有支援Declarative Shadow DOM,在使用class時可以不用使用attachShadow方法生成SHadow DOM(因為己經在解析HTML時生成了),但事件的綁定之類的還是要宣告。

class MyComponent extends HTMLElement {
    constructor() {
        super();
        this.render = this.render.bind(this);
        this.ClickEvent = this.ClickEvent.bind(this);
        this.ClickEvent2 = this.ClickEvent2.bind(this);
        // 如果在不支援Declarative Shadow DOM的瀏覧器中使用要加這一段
        // 因為有支援的話this.shadowRoot就不會是null
        if (!this.shadowRoot) {
            this.attachShadow({mode: 'open'});
            this.shadowRoot.appendChild(this.render())
        }
    }
    connectedCallback() {
        // 不管有沒有支援Declarative Shadow DOM都要加這一段,因為事件綁定只能由JS來做
        // javascript 的 hydration
        this.root.getElementById('card-title').addEventListener('click', this.ClickEvent)
        this.root.getElementById('card-slot').addEventListener('click', this.ClickEvent2)
    }
    disconnectedCallback() {
        // 不管有沒有支援Declarative Shadow DOM都要加這一段,因為事件綁定只能由JS來做
        // javascript 的 hydration
        this.root.getElementById('card-title').removeEventListener('click', this.ClickEvent)
        this.root.getElementById('card-slot').removeEventListener('click', this.ClickEvent2)
    }
    ...
    // 如果有支援Declarative Shadow DOM,就可以不需要這個函式
    render() {
        const template = document.createElement('template');
        template.innerHTML = `
            <style>${this.style}</style>
            <div class='card'>
                <h2 id='card-title' class='card-title'>title</h2>
                <div id='card-content' class='card-content'>content</div>
                <slot id='card-slot'></slot>
                <div id='card-content2' class='card-content2'>content2</div>
            </div>
        `;
        return template.content;
    }
    ClickEvent() {
        console.log('click')
    }
    ClickEvent2() {
        const newEvevt = new CustomEvent('clickSlot', {
            bubbles: true,
            composed: true,
            detail: {
                name: 'click'
            }
        })
        this.dispatchEvent(newEvevt)
    }
}
customElements.define('my-com', MyComponent);

上一篇
[Day12] web component 的歷史-那些己經廢除或不穩定的部分
下一篇
[Day14] web component 的應用-和框架合作
系列文
web component - 次世代網頁技術的重要拼圖30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言