观察目标节点上尚不存在的突变 [英] Observe mutations on a target node that doesn't exist yet

查看:106
本文介绍了观察目标节点上尚不存在的突变的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有可能在DOM节点上观察到尚不存在的突变?

Is it possible to observer mutations on a DOM node that doesn't exist yet?

示例:

我的应用程序在某个时刻创建一个div:< div id =messagedata-message-content =foodata-message-type =bar />

My app creates a div at some point: <div id="message" data-message-content="foo" data-message-type="bar" />.

我想留意创作&改变这个div。

I want to watch for the creation & change of this div.

var mutationObserver = new MutationObserver(function(mutations){
  // Some code to handle the mutation.
});

mutationObserver.observe(
    document.querySelector('#message'),
        { 
            attributes: true, 
            subtree: true, 
            childList: true, 
            characterData: false 
        }
    );
);

现在这会返回错误,因为#消息为空(尚未创建div)。

Right now this returns an error since #message is null (the div hasn't been created yet).

无法执行'观察'' MutationObserver':参数1不是'Node'类型。

一个明显的解决方案是观察 body 并检查是否有任何突变是 div#Message 的创建,但这似乎是一个坏主意/或可能对性能不利。

An obvious solution is to watch the body and check if any of the mutations are the creation of div#Message, but this seems like a bad idea / or possibly bad for performance.

推荐答案

只能观察现有节点。

但不要担心,因为与枚举所有突变添加的节点相比,getElementById的速度非常快,等待元素出现将不会产生任何负担,就像你在Devtools - > Profiler面板中看到的那样。

But don't worry, since getElementById is insanely fast compared to enumeration of all mutations' added nodes, waiting for the element to appear won't be taxing at all as you will see in Devtools -> Profiler panel.

function waitForAddedNode(params) {
    new MutationObserver(function(mutations) {
        var el = document.getElementById(params.id);
        if (el) {
            this.disconnect();
            params.done(el);
        }
    }).observe(params.parent || document, {
        subtree: !!params.recursive,
        childList: true,
    });
}

用法:

waitForAddedNode({
    id: 'message',
    parent: document.querySelector('.container'),
    recursive: false,
    done: function(el) {
        console.log(el);
    }
});

始终使用devtools探查器并尝试使观察者回调消耗不到1%的CPU时间。

Always use the devtools profiler and try to make your observer callback consume less than 1% of CPU time.


  • 尽可能观察未来节点的直接父节点(子树:false

  • 在MutationObserver回调中使用getElementById,getElementsByTagName和getElementsByClassName,避免使用querySelector,特别是极慢的querySelectorAll。

  • 如果在MutationObserver回调中,querySelectorAll绝对是不可避免的,首先执行querySelector检查,平均来说这样的组合会快得多。

  • 不要使用像forEach,filter等那样需要在MutationObserver回调中回调的数组方法,因为在Javascript函数调用中对于(var i = 0 ....)循环的经典而言,这是一项昂贵的操作,并且MutationObserver回调可能每秒发射100次,数十,数百或数千复杂现代页面上每批突变中的 addedNodes

  • 不要使用,如 for(v of of something)在MutationObserver回调中,除非你进行反编译,结果代码运行速度与经典<$ c一样快$ c> for loop。

  • Whenever possible observe direct parents of a future node (subtree: false)
  • Use getElementById, getElementsByTagName and getElementsByClassName inside MutationObserver callback, avoid querySelector and especially the extremely slow querySelectorAll.
  • If querySelectorAll is absolutely unavoidable inside MutationObserver callback, first perform the querySelector check, on the average such combo will be much faster.
  • Don't use Array methods like forEach, filter, etc. that require callbacks inside MutationObserver callback because in Javascript function invocation is an expensive operation compared to the classic for (var i=0 ....) loop, and MutationObserver callback may fire 100 times per second with dozens, hundreds or thousands of addedNodes in each batch of mutations on complex modern pages.
  • Don't use the slow ES2015 loops like for (v of something) inside MutationObserver callback unless you transcompile and the resultant code runs as fast as the classic for loop.

这篇关于观察目标节点上尚不存在的突变的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆