1. 为什么用 shadow dom

应用shadom dom能够让组件与其余组件、组件与dom树进行隔离,实现封装。

如MDN中所写:

Web components 的一个重要属性是封装——能够将标记构造、款式和行为暗藏起来,并与页面上的其余代码相隔离,保障不同的局部不会混在一起,可使代码更加洁净、整洁。

每一个 shadow dom 都是一个独立的、暗藏的dom树,附加在了一个元素上。

2. 在custom element中应用shadow dom

接第一篇末的代码

class CommentCard extends HTMLElement{    constructor(){        super();        //将shadow dom附加在自定义元素中                let shadow = this.attachShadow({mode: 'open'});        let templateEle = document.getElementById('commentCardTemplate');        let content = templateEle.content.cloneNode(true);                content.querySelector('img').src = this.dataset.avatar;        content.querySelector('.nickname').innerHTML = this.dataset.nickname;        //向shadow dom中追加元素        shadow.appendChild(content);    }}

Element.attachShadow承受一个配置对象作为参数,它蕴含一个属性 mode
mode设置为open时,则能够从内部流动并操作shadow dom。
mode设置为closed时,内部将无法访问到shadow dom。

一般来说,我认为没有必要将mode设置为closed。即便在custom elements类定义的外部,咱们也无奈对shadow dom进行操作。这将影响咱们对custom elements的灵活处理,比方款式操作、事件绑定等。这样太不不便了。

3. 操作shadow dom

通过Element.shadowRoot能够获取shadow dom的根结点。
其它操作与惯例DOM操作统一。
比方给某个元素增加事件绑定。

class CommentCard extends HTMLElement{    constructor(){        super();        let shadow = this.attachShadow({mode: 'open'});        let templateEle = document.getElementById('commentCardTemplate');        let content = templateEle.content.cloneNode(true);                //向shadow dom中追加元素        shadow.appendChild(content);        this.shadowRoot.querySelector('.nickname').addEventListener('click', (e) => {            this._showBubble(e.target);        })    }        ...}