MutationObserver 能否在突变之前进行更改?
Can MutationObserver make changes just right before mutation?
我需要使用 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']")"
returns一个元素)。
我没有找到任何 method/property 来拒绝 MutationObserver 中的 dom 更改。有没有一种方法可以实现我想要的,而无需每次都检查整个文档?
我不清楚突变观察者返回的 NodeList
是否是 "live",因为对该列表中节点的更改会立即反映在 DOM 上。但这并不重要,因为您只是用它来创建 jQuery 包装集。您上面获得的基本代码按预期工作(请参阅下面的简化代码段),这意味着还有其他因素阻止您的 hide()
调用按预期工作。
我最好的理解是,您无法拦截和阻止对 DOM 的更改——MutationObserver 在相关突变已经发生后被触发。这意味着你不是在打断或拦截突变,而是对其做出反应。在您的情况下,这可能会导致意外的 "flashing" 行为,因为添加然后删除节点。在这种情况下,更好的解决方案是将新添加的节点设置为默认隐藏的样式,然后添加 class/style 以显示它们或将它们从突变观察器过滤器的 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>
我需要使用 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']")"
returns一个元素)。
我没有找到任何 method/property 来拒绝 MutationObserver 中的 dom 更改。有没有一种方法可以实现我想要的,而无需每次都检查整个文档?
我不清楚突变观察者返回的 NodeList
是否是 "live",因为对该列表中节点的更改会立即反映在 DOM 上。但这并不重要,因为您只是用它来创建 jQuery 包装集。您上面获得的基本代码按预期工作(请参阅下面的简化代码段),这意味着还有其他因素阻止您的 hide()
调用按预期工作。
我最好的理解是,您无法拦截和阻止对 DOM 的更改——MutationObserver 在相关突变已经发生后被触发。这意味着你不是在打断或拦截突变,而是对其做出反应。在您的情况下,这可能会导致意外的 "flashing" 行为,因为添加然后删除节点。在这种情况下,更好的解决方案是将新添加的节点设置为默认隐藏的样式,然后添加 class/style 以显示它们或将它们从突变观察器过滤器的 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>