Javascript 如何断开匿名MutationObserver与文档元素的连接,而不使用其克隆替换元素?
在创建一个应该更改多个文档元素属性的tampermonkey脚本时,我遇到了一个使用事件侦听器阻止对该属性进行任何更改的站点。为了对抗这种行为,我可以将元素替换为它们的克隆,如下所示:Javascript 如何断开匿名MutationObserver与文档元素的连接,而不使用其克隆替换元素?,javascript,mutation-observers,Javascript,Mutation Observers,在创建一个应该更改多个文档元素属性的tampermonkey脚本时,我遇到了一个使用事件侦听器阻止对该属性进行任何更改的站点。为了对抗这种行为,我可以将元素替换为它们的克隆,如下所示: const map = new Map(); function read() { for (let image of [...document.getElementsByTagName('img')]) { const clone = image.cloneNode(/* with ch
const map = new Map();
function read() {
for (let image of [...document.getElementsByTagName('img')]) {
const clone = image.cloneNode(/* with children */true);
// TODO: modify the clone
map.set(image, clone);
}
}
read();
function write() {
for (let [image, clone] of map) {
image.parentNode.replaceChild(clone, image);
}
}
write();
map.clear();
但使用这种方法存在一个问题:浏览器(Chrome71)在操作结束时会重新计算样式,如果元素数量较大(10个元素-无抖动,100个元素-抖动),有时会抖动布局。我尝试使用请求的动画帧修改写入循环函数:
window.requestAnimationFrame(document.replaceChild.bind(image.parentNode, clone, image));
但它仍然会破坏布局。
尝试在循环中插入暂停:
async function write() {
for (let [image, clone] of map) {
await new Promise(window.requestAnimationFrame);
image.parentNode.replaceChild(clone, image);
}
}
没有变化。试图将数组中的元素分割成小块并操作每个块,但浏览器最终仍然懒散地重新计算样式并重击布局。
因此,我可以使用以下内容删除每个事件侦听器,而不是用克隆替换每个元素:
for (let image of [...document.getElementsByTagName('img')]) {
const listeners = getEventListeners(image);
for (let event_type in listeners) {
for (let event of listeners[event_type]) {
image.removeEventListener(event.type, event.listener, event.useCapture);
}
}
}
虽然这解决了问题,但仍然存在一个问题:如果站点使用的不是事件侦听器,而是MutationObserver来防止修改文档元素,该怎么办?有没有一种方法可以删除MutationObserver而不使用其克隆替换文档元素
虽然我知道修改很多元素的属性仍然会迫使浏览器重新流,但我的问题仍然存在。没有办法断开anonymous MutationObserver,但这并不意味着没有其他解决方案 我相信您不需要更改页面上的所有链接。
你只需要截取一个用户试图跟随的链接 请参阅下面的代码片段 我们想要更改
href
属性,并且观察者正在捕获该属性:
//匿名观察者:
(新的MutationObserver(函数)(mutationsList,observer){
for(突变列表的var突变){
如果(
突变类型=='attributes'&&
mutation.target.href!=='https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png'
) {
log('修改了'+mutation.attributeName+'属性');
mutation.target.href=https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png'
}
}
}))
.观察(
document.querySelector('html'){
属性:正确,
子树:真
}
);
document.querySelectorAll('a').forEach(函数(a){
a、 href='https://yastatic.net/www/_/x/Q/xk8YidkhGjIGOrFm_dL5781YA.svg';
});代码>
没有这样的方法。另外请注意,该站点还可以使用IntersectionObserver或哑间隔检查检测从DOM中删除的元素,然后重新附加到新元素。更具体地说,您在谈论什么网站?最后你想做什么?@wOxxOm,谢谢。请注意。@KoshVery,所讨论的站点是。Tampermonkey脚本正在修改链接/锚标记的href,这样我就可以跳过链接处理程序(如steam链接过滤器),直接进入理想的站点。谢谢在不克隆链接标记的情况下,绕过link href属性上的observer确实是一种解决方案。但有两个细节让我感到不舒服:在每个新链接的无限滚动页面上都会有新的侦听器(我的计算机不会爆炸吗?),用户不能在悬停时预览url(这不是很糟糕吗?)。另外,虽然您的回答很有用,但我不知道是否应该标记我的问题已回答,“因为据我所知,无法断开document元素上的匿名MutationObserver?”即“sme-还有谁,谢谢您的留言!我已经更新了我的答案来明确回答你的问题——如果是匿名的,你不能断开它。关于无限滚动,如果您对加载无限内容感到满意,也不用担心事件侦听器=))认真地说,您可以设置一个委托的touchstart/mousedown
侦听器,然后在其回调集中单击侦听器--您可能会节省一些内存。第二,用户不能在悬停时预览url——这也是可以解决的,但超出了这个问题的范围。