MutationObserver 可以在突变之前进行更改吗?

问题描述 投票:0回答:2

我需要使用mutationobserver来防止DOM更改。

我(过去)使用以下代码来防止特定更改:

document.bind("DOMSubtreeModified", function() {
   document.find('.Xx.xJ:Contains("wham")').closest("[jsmodel='XNmfOc']").hide();
});

由于性能原因,我不想检查任何 dom 更改的完整文档,而只想添加内容,所以我更改为(现在):

 var observer = new MutationObserver(function (mutations) {
        mutations.forEach(function (mutation) {
            [].slice.call(mutation.addedNodes).forEach(function (addedNode) {
               StartFilter(addedNode);                    

            });
        });
    });

    observer.observe(document, {
        childList: true,
        subtree:true,
        characterData:true,
        attributes:true        
    });

function StartFilter(newNode) {
   $(newNode).find('.Xx.xJ:Contains("wham")').closest("[jsmodel='XNmfOc']").hide();
}

但这并没有真正起作用。我的猜测是“newNode”并不是真正对 DOM 元素的引用。 (选择器有效,

"$(newNode).find('.Xx.xJ:Contains("wham")').closest("[jsmodel='XNmfOc']")"
返回一个元素)。

我没有找到任何方法/属性来拒绝 MutationObserver 中的 dom 更改。有没有一种方法可以实现我想要的目标,而无需每次都检查整个文档?

javascript jquery mutation-observers
2个回答
5
投票

我不清楚突变观察者返回的

NodeList
是否是“实时”的,即该列表中节点的更改会立即反映在 DOM 上。但这并不重要,因为您只是使用它来创建 jQuery 包装集。上面的基本代码按预期工作(请参阅下面的简化代码片段),这意味着还有其他原因阻止您的
hide()
调用按预期工作。

我最好的理解是,你无法拦截和阻止对 DOM 的更改——MutationObserver 在相关的突变已经发生后被触发。这意味着你不会中断或拦截突变,而是对其做出反应。在您的情况下,当添加然后删除节点时,这可能会导致意外的“闪烁”行为。在这种情况下,更好的解决方案是将新添加的节点设置为默认隐藏的样式,然后添加类/样式以在突变观察者过滤器中显示它们或从 DOM 中删除它们。

var container = document.querySelector('.container');
var addNodeButton = document.querySelector('#add');
var addNodeWithHideButton = document.querySelector('#addWithHide');

var makeAddNode = function(includeHide) {
  return function() {
    var p = document.createElement('p');
    var s = document.createElement('span');
    var msg = 'Appended at ' + new Date().getTime();
    if (includeHide) {
      msg += ' (hide)';
    }
    var t = document.createTextNode(msg);
    s.appendChild(t);
    p.appendChild(s);
    container.appendChild(p);
    console.log('appended::', p);
  };
};

var makeNode = makeAddNode(false);
var makeNodeWithHidden = makeAddNode(true);

addNodeButton.addEventListener('click', makeNode);
addNodeWithHideButton.addEventListener('click', makeNodeWithHidden);

var toArray = function() {
  return [].slice.call(arguments);
};

var observer = new MutationObserver(function (mutations) {
  mutations.forEach(function (mutation) {
    toArray(mutation.addedNodes).forEach(function (addedNode) {
      StartFilter(addedNode);
    });
  });
});

observer.observe(document, {
  childList: true,
  subtree:true,
  characterData:true,
  attributes:true
});

function StartFilter(newNode) {
  var $n = $(newNode);
  console.log('$n::', $n);
  $n.find('span:contains(hide)').fadeOut(1500);
  //   $(newNode).find('.Xx.xJ:Contains("wham")').closest("[jsmodel='XNmfOc']").hide();
}
.container {
  width: 80%;
  border: 1px solid green;
  padding: 1rem;
  margin: 1rem auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button id="add">Add node without "hide"</button>
<button id="addWithHide">Add node with "hide"</button>
<div class="container"></div>


0
投票

由于现有答案不够明确,这里有更详细的解释:

MutationObserver
paint事件发生之前捕获DOM更改(突变),这意味着这些更改是在动画帧之前观察到的。这个时机至关重要,因为它允许您在 DOM 的修改被渲染到屏幕上之前拦截并调整它们。 通过

MutationObserver

,您可以:


观察属性变化并
    防止它们被视觉渲染
  • 重新添加已删除的元素
  • 或删除 DOM 中添加的元素,在这些更改变得可见之前有效地撤消这些更改。 回滚其他类型的突变,让您可以细粒度地控制视觉变化。
  • 此行为可以在任何视觉影响之前管理或阻止修改,这在您想要管理 DOM 稳定性、限制不需要的更改或推迟繁重的布局操作的情况下非常有用。

有关绘画管道如何工作的进一步阅读和更多信息,请参阅 Chromium 文档:

铬漆舞台
希望这有助于澄清!

© www.soinside.com 2019 - 2024. All rights reserved.