MutationObserver API

One of my favorite web tricks was using CSS and JavaScript to detect insertion and removal of a DOM node, detailed in Detect DOM Node Insertions with JavaScript and CSS Animations.  The technique and blog post were published during a time when we didn't have a reasonable API for detecting such events.  Nowadays we have MutationObserver, an API made to efficiently detect loads of node operations.  Let's have a look!

我最喜欢的网络技巧之一是使用CSS和JavaScript来检测DOM节点的插入和移除,有关详细信息,请参见使用JavaScript和CSS动画检测DOM节点插入 。 该技术和博客文章是在我们没有合理的API来检测此类事件的时候发布的。 如今,我们有了MutationObserver ,该API旨在有效检测节点操作的负载。 我们来看一下!

基本的MutationObserver API (Basic MutationObserver API)

The MutationObserver API is a bit complicated for me but here's the basic setup:

MutationObserver API对我来说有点复杂,但这是基本设置:


var observer = new MutationObserver(function(mutations) {
	// For the sake of...observation...let's output the mutation to console to see how this all works
	mutations.forEach(function(mutation) {
		console.log(mutation.type);
	});    
});
 
// Notify me of everything!
var observerConfig = {
	attributes: true, 
	childList: true, 
	characterData: true 
};
 
// Node, config
// In this case we'll listen to all changes to body and child nodes
var targetNode = document.body;
observer.observe(targetNode, observerConfig);


There's a lot to using the MutationObserver, but the breakdown is:

使用MutationObserver的工作很多,但细目如下:

  • Create an instance of MutationObserver with a callback to handle any event thrown its way

    创建一个带有回调的MutationObserver实例,以处理抛出的所有事件

  • Create a set of options for the MutationObserver

    MutationObserver创建一组选项

  • Call the observe method of the MutationObserver instance, passing it the node to listen to (..and its children) and the option list.

    调用MutationObserver实例的observe方法,向其传递要侦听的节点(..及其子节点)和选项列表。

  • At the time you want to stop observing, call disconnect

    您要停止观察时,请disconnect

MutationObserver选项 (MutationObserver Options)

MDN provides detail on the options for MutationObserver:

MDN提供有关MutationObserver选项的详细信息:

  • childList: Set to true if additions and removals of the target node's child elements (including text nodes) are to be observed.

    childList :如果要观察到目标节点的子元素(包括文本节点)的添加和移除,则设置为true。

  • attributes: Set to true if mutations to target's attributes are to be observed.

    attributes :如果要观察到目标属性的变异,则设置为true。

  • characterData Set: to true if mutations to target's data are to be observed.

    characterData Set :如果要观察到目标数据的突变,则为true。

  • subtree: Set to true if mutations to not just target, but also target's descendants are to be observed.

    subtree :如果不仅要观察目标,还要观察目标的后代,则设置为true。

  • attributeOldValue: Set to true if attributes is set to true and target's attribute value before the mutation needs to be recorded.

    attributeOldValue :如果属性设置为true且需要记录突变之前目标的属性值,则设置为true。

  • characterDataOldValue: Set to true if characterData is set to true and target's data before the mutation needs to be recorded.

    characterDataOldValue :如果characterData设置为true,并且需要记录突变之前的目标数据,则设置为true。

  • attributeFilter: Set to an array of attribute local names (without namespace) if not all attribute mutations need to be observed.

    attributeFilter :如果不需要观察所有的属性突变,则设置为属性本地名称(无名称空间)的数组。

That's a lot to be aware of when listening to one node and/or child nodes!

在侦听一个节点和/或子节点时要注意很多!

MutationRecord: MutationObserver处理程序结果 (MutationRecord:  MutationObserver Handler Results)

The resulting object when a mutation is observed is detailed as well:

观察到突变时产生的对象也很详细:

  • type (String): Returns attributes if the mutation was an attribute mutation, characterData if it was a mutation to a CharacterData node, and childList if it was a mutation to the tree of nodes.

    type (String) :如果突变是属性突变,则返回属性;如果CharacterData是CharacterData节点的突变,则返回characterData;如果是节点树的突变,则返回childList。

  • target (Node): Returns the node the mutation affected, depending on the type. For attributes, it is the element whose attribute changed. For characterData, it is the CharacterData node. For childList, it is the node whose children changed.

    target (Node) :根据类型返回受突变影响的节点。 对于属性,它是其属性已更改的元素。 对于characterData,它是CharacterData节点。 对于childList,它是其子项已更改的节点。

  • addedNodes (NodeList): Return the nodes added. Will be an empty NodeList if no nodes were added.

    addedNodes (NodeList) :返回添加的节点。 如果未添加任何节点,则该节点将为空。

  • removedNodes (NodeList): Return the nodes removed. Will be an empty NodeList if no nodes were removed.

    removedNodes (NodeList) :返回已删除的节点。 如果未删除任何节点,则该节点将为空。

  • previousSibling (Node): Return the previous sibling of the added or removed nodes, or null.

    previousSibling (Node) :返回添加或删除的节点的上一个兄弟节点,或者为null。

  • nextSibling (Node): Return the next sibling of the added or removed nodes, or null.

    nextSibling (Node) :返回添加或删除的节点的下一个同级,或者为null。

  • attributeName (String): Returns the local name of the changed attribute, or null.

    attributeName (String) :返回已更改属性的本地名称,或者为null。

  • attributeNamespace (String): Returns the namespace of the changed attribute, or null.

    attributeNamespace (String) :返回已更改属性的名称空间,或者为null。

  • oldValue (String): The return value depends on the type. For attributes, it is the value of the changed attribute before the change. For characterData, it is the data of the changed node before the change. For childList, it is null.

    oldValue (String) :返回值取决于类型。 对于属性,它是更改前更改的属性的值。 对于characterData,它是更改之前更改的节点的数据。 对于childList,它为null。

Whew.  So let's take look at some realistic use cases of MutationObserver.

ew。 因此,让我们看一下MutationObserver一些实际用例。

检测何时插入节点 (Detect When a Node is Inserted)

The use case in my Detect DOM Node Insertions with JavaScript and CSS Animations post was detecting node insertion, so let's create a snippet which detects node insertion:

我的《使用JavaScript和CSS动画检测DOM节点插入 》一文中的用例是检测节点插入,因此让我们创建一个片段来检测节点插入:


// Let's add a sample node to see what the MutationRecord looks like
// document.body.appendChild(document.createElement('li'));

{
	addedNodes: NodeList[1], // The added node is in this NodeList
	attributeName: null,
	attributeNamespace: null,
	nextSibling: null,
	oldValue: null,
	previousSibling: text,
	removedNodes: NodeList[0],
	target: body.document,
	type: "childList"
}


The resulting MutationRecord shows addedNodes: NodeList[1], meaning that a node has been added somewhere lower in the tree.  The type is childList.

生成的MutationRecord显示出addedNodes: NodeList[1] ,这意味着已在树的较低位置添加了一个节点。 typechildList

检测何时删除节点 (Detect When a Node is Removed)

Removing a node shows the following MutationRecord:

删除节点将显示以下MutationRecord:


// Now let's explore the MutationRecord when a node is removed
// document.body.removeChild(document.querySelector('div'))

{
	addedNodes: NodeList[0],
	attributeName: null,
	attributeNamespace: null,
	nextSibling: text,
	oldValue: null,
	previousSibling: null,
	removedNodes: NodeList[1], // The removed node is in this NodeList
	target: body.document,
	type: "childList"
}


This action also shows a type of childList but now removeNodes now has the NodeList[1], a NodeList with the removed node.

此操作还显示了childListtype ,但是removeNodes现在具有NodeList[1] ,即具有已删除节点的NodeList

检测属性更改 (Detect Attribute Changes)

If an attribute is changed on any element, you'll be quick to know about it; the MutationRecord will show:

如果在任何元素上更改了属性,您将很快了解它。 MutationRecord将显示:


// What do attribute changes look like?
// document.body.setAttribute('id', 'booooody');

{
	addedNodes: NodeList[0],
	attributeName: "id",
	attributeNamespace: null,
	nextSibling: null,
	oldValue: null,
	previousSibling: null,
	removedNodes: NodeList[0],
	target: body#booooody.document,
	type: "attributes"
}


Also note that the target will show the node for which the attributes was changed.  The oldValue will display its former value and while a normal getAttribute check give you the new attributes value.

另请注意, target将显示其属性已更改的节点。 oldValue将显示其以前的值,而常规的getAttribute检查将为您提供新的属性值。

别听了! (Stop Listening!)

If you're looking to write the ultimate efficient app, you'll only be adding listeners for the period you need them and then removing them when you're done:

如果您要编写最终高效的应用程序,则只需在所需的时间内添加监听器,然后在完成时将其删除:


observer.disconnect();


The MutationObserver instance has a disconnect method to stop listening.  Since your app may have many, many DOM operations, you may want the power to disconnect your listener for the duration of the time your user interacts with the page.

MutationObserver实例具有disconnect方法以停止侦听。 由于您的应用程序可能有很多很多DOM操作,因此您可能希望在用户与页面进行交互的过程中断开监听器的连接。

The MutationObserver API seems a tad verbose but it's powerful, informative, and ultimately hack free.  Daniel Buchner's brilliant original "hack" provides better support for node addition and removal but MutationObserver should probably be used if possible.

MutationObserver API似乎有点冗长,但功能强大,信息量大,并且最终不受黑客攻击。 丹尼尔·布赫纳(Daniel Buchner)出色的原创“ hack”为节点添加和删除提供了更好的支持,但如果可能的话,应该使用MutationObserver

翻译自: https://davidwalsh.name/mutationobserver-api

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值