shadow dom - 知道 dom 何时渲染/更改

Posted

技术标签:

【中文标题】shadow dom - 知道 dom 何时渲染/更改【英文标题】:shadow dom - know when dom is rendered/changed 【发布时间】:2018-04-10 06:17:35 【问题描述】:

我正在编写一个 chrome 扩展,它会在页面加载或更改时修改元素属性。

我使用 Mutation Observer 执行此操作。然而,当 shadow-dom(即嵌入的 twitter 帖子)被加载/更改时,观察者的处理程序不会被调用。

有没有办法在 shadow-dom 加载/更改时获取事件或将突变观察者挂钩到它?

谢谢!

【问题讨论】:

【参考方案1】:

如果内容只是简单地使用slotchange 事件进行开槽是最简单的,它不会触发更深层次的更改,只是开槽(与观察子树和 childList 的突变观察者不同);它就像 slot 上 childList 的观察者,也是分离组件和 slot 内容之间关注点的最佳方式;当由于某种原因观察组件各自的shadowRoot 或更深的树中的更改时,请使用@Supersharp 的答案中的突变观察者,除了将subtree 添加到配置中(或者可能使用各自的shadowRoots 设置子级来调度事件) composed: true, cancelable: true, bubbles: true 通知祖先到你的组件的变化;

需要向 shadowRoot 添加一个插槽,并将事件侦听器添加到它,如 shadowRoot.innerhtml = <slot onslotchange=...>empty slot</slot> 适应在上下文中工作

https://developer.mozilla.org/docs/Web/API/HTMLSlotElement/slotchange_event

【讨论】:

【参考方案2】:

您可以使用 Shadow DOM 简单地 observe() 元素的 shadowRoot 属性。

customElements.define('image-list', class extends HTMLElement 
  connectedCallback() 
    var observer = new MutationObserver(function(mutations) 
      mutations.forEach(function(mutation) 
        //Detect <img> insertion
        if (mutation.addedNodes.length)
          console.info('Node added: ', mutation.addedNodes[0])
      )
    )

    this.attachShadow(mode: 'open').innerHTML = '<img >'

    observer.observe(this.shadowRoot, childList: true)
  

  addImage() 
    var img = document.createElement('img')
    img.alt = ' new image '
    this.shadowRoot.appendChild(img)
  
)
<image-list id=LI>
</image-list>
<button onclick="LI.addImage()">Add image</button>

【讨论】:

太棒了!这是否意味着我需要我的主要观察者将新观察者挂接到它遇到的任何影子 dom? @kofifus 是的,你会的 这个答案很有帮助,但是如果我需要检测影子根本身的添加怎么办?当初始影子根添加到&lt;image-list&gt; 元素时,mutationObserver 不会触发。我尝试更新观察者以观察父元素,但它似乎无法检测到 shadowRoot 的添加。 我还没有找到在自定义元素构造函数之外添加 shadowRoot 的实例/用例。我很有信心,如果我等待customElements.whenDefined(nodeName) 解决这个问题,如果没有 shadowRoot,它就不会存在。我想这取决于您的用例以及您需要的确定程度。 @Keven 恐怕这是不可能的。另一种解决方法是重载 attachShadow() 方法。那是猴子补丁,并不总是推荐的。

以上是关于shadow dom - 知道 dom 何时渲染/更改的主要内容,如果未能解决你的问题,请参考以下文章

shadow dom 隔离代码 封装

每日思考(2020/01/03)

IOS Safari 是不是支持 Shadow DOM?

怎么在ng-repeat生成的元素上操作dom

有人知道如何使用 selenium webdriver 识别 shadow dom web 元素吗?

如何知道动态创建的 Angular 组件何时可以在 DOM 中请求?