首页 > 解决方案 > 使用突变观察者跟踪页面中的所有元素

问题描述

我需要以所有元素为目标,class="kendoTooltip"并在该类的任何元素上运行 jQuery 函数。

html的一个例子是;

<div class="document_wrapper">
    <div>
        <div class="kendoTooltip">Tooltip!</div>
    </div>
</div>

我一直在尝试使用突变观察器,但无法定位页面深处的元素。

使用下面的代码,我得到了最接近的结果,但问题似乎是突变观察者只监视音符本身及其直接子元素。我也尝试过递归调用它,但没有成功。

var mutationObserver = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
        if (!mutation.target.classList.contains('isRendered') && mutation.target.classList.contains('kendoTooltip')) {
            renderTooltip(mutation.target);
            mutation.target.classList.add('isRendered');
        }
    });
});

mutationObserver.observe(document.documentElement || document.body, {
    childList: true,
    subtree: true
});

标签: javascriptmutation-observers

解决方案


作为记录,与某些评论中所说的相反,subtree选项将针对所有后代:孩子,孩子的孩子......观察到的元素,但仅限于直接从 DOM 添加或删除的那些。见这里这里。顺便说一句,有一个陷阱。想象一下,你想观察一个video标签,它没有直接附加到 DOM 上,而是附加到一个分离的 DOM 上,比如 adiv.video-container并且它是添加到 DOM 的那个容器。

const mutationInstance = new MutationObserver((mutations) => {
  // The <video> is not directly added to the DOM, so wee need to query it on each added nodes
  const videoContainer = mutations
    .reduce((addedNodes, mutationRecord) => {
      return [
        ...addedNodes,
        ...(Array.from(mutationRecord.addedNodes)),
      ];
    }, [])
    .find((element) => {
      return element.querySelector("video") !== null;
    });
   
   const videoElement = videoContainer.querySelector("video");
   console.log('Video element is', videoElement);
});

mutationInstance.observe(document, {
  subtree: true,
  childList: true,
});

触发突变的代码

const div = document.createElement('div');
div.classList.add('video-container');
const video = document.createElement('video');

// This **does not trigger** a mutation on the document
div.appendChild(video);

// This **triggers** a mutation on the document
document.body.appendChild(div);

推荐阅读