Shadow DOM 模式

Open模式

你是否在上述 attachShadow() 方法里注意到 {mode: "open"} 配置? open 模式提供了一种我们可以通过JavaScript来访问元素的shadow DOM的方式,这种模式也允许我们通过shadow DOM来访问宿主元素。

这是通过我们在 open 模式下使用 attachShadow() 时候创建的两个隐式属性来实现的。

  1. 被创建元素获得了一个叫做 shadowRoot 的属性,该属性指向了shadow DOM;
  2. shadowRoot 获得了一个叫做 host 的属性,该属性指向该元素本身;
  1. // From the "How to create shadow DOM" example
  2. el.attachShadow({ mode: 'open' });
  3. // Just like prototype & constructor bi-directional references, we have...
  4. el.shadowRoot; // the shadow root.
  5. el.shadowRoot.host; // the el itself.

Closed 模式

{mode: "closed"} 传递给 attachShadow(),来创建一个闭合的shadow DOM。该操作使得JavaScript无法访问shadow DOM。

  1. el.shadowRoot; // null

应该选择哪种模式?

几乎大部分场景下使用open模式的shadow DOMs ,因为这种模式可以让组件开发者和使用者能够按照他们的需求去做些事情。

还记得我们做过 el.shadowRoot 那部分么?在 closed 模式下,是不生效的。closed 模式使得元素不会有对本身shadow DOM的引用。当在创建一个元素并想要通过shadow DOM 进行一些操作时候,closed 模式会造成阻碍。

  1. class CustomPicture extends HTMLElement {
  2. constructor() {
  3. this.attachShadow({ mode: 'open' }); // this.shadowRoot exists. add or remove stuff in there using this ref.
  4. this.attachShadow({ mode: 'closed' }); // this.shadowRoot returns null. Bummer!
  5. }
  6. }
  7. // You could always do the following in your constructor.
  8. // but it totally defies the purpose of using closed mode.
  9. this._shadowRoot = this.attachShadow({ mode: 'closed' });

此外,封闭模式不是一种安全的机制。他只是给人一种虚假的安全感。没有人可以阻止其他人修改 Element.prototype.attachShadow()