MutationObserver(下)

本文详细介绍了MutationObserver对象及其初始化参数MutationObserverInit,展示了如何利用这些参数观察DOM节点的属性、字符数据及子节点的变化,并提供了丰富的示例代码。

MutationObserverInit对象

MutationObserverInit对象用于控制对目标节点的观察范围。粗略的讲观察者可以观察的事件包括属性变化、文本变化和子节点变化。

MutationObserverInit对象属性:

subtree

布尔值,表示除了目标节点,是否观察目标节点的子树(后代)

如果是false,则只观察目标节点的变化;如果是true,则观察目标节点及其整个子树

默认为false

attributes布尔值,表示是否观察目标节点的属性变化
attributeFilter字符串数组,表示要观察哪些属性的变化
attributeOldValue

布尔值,表示 MutationRecord是否记录变化之前的属性值

把这个值设置为true也会将attributes的值转换为true

默认为false

characterData

布尔值,表示修改字符数据是否触发变化事件

默认为false

characterDataOldvalue

布尔值,表示 MutationRecord是否记录变化之前的字符数据

把这个值设置为true也会将 characterData的值转换为true

默认为false

childList

布尔值,表示修改目标节点的子节点是否触发变化事件

默认为false

注:在调用observer()时,MutationObserverInit对象中的attributes、characterData和childList属性必须至少有一项为true(无论是直接<br>设置这几个属性,还是通过设置attributeOldValue等属性间接导致它们的值转换为true)。否则会抛出错误,因为没有任何变化事件可能触发回调

1、观察属性

        MutationObserver可以观察节点属性的添加、移除和修改。要为属性变化注册回调,需要在            MutationObserverInit对象中将attributes属性设置为true

        例:

        let mutationAttr1 = new                MutationObserver((MutationRecords)=>console.log(MutationRecords));

        mutationAttr1.observe(document.body,{attributes:true});

        // 添加属性

        document.body.setAttribute('foo','bar');

       // 修改属性

        document.body.setAttribute('foo','baz');

       // 删除属性

        document.body.removeAttribute('foo');

        以上的变化都被记录下来了

        // [MutationRecord, MutationRecord, MutationRecord]

        把attributes设置为true的默认行为是观察所有属性,但不会在MutationRecord对象中记录原来的值。如果想观察某个或某几个属性,可以使用attributeFilter

        属性来设置白名单,即一个属性明字符串数组

        let mutationAttr2 = new         MutationObserver((MutationRecords)=>console.log(MutationRecords));

        mutationAttr2.observe(document.body,{attributeFilter:['foo']});

        //添加白名单

        document.body.setAttribute('foo','bar');

        //添加被排除的属性

        document.body.setAttribute('baz','qux');

        //只有foo属性的变化被记录了

        // [

        //     {

        //         addedNodes:NodeList[],

        //         attributeName:"foo",

        //         attributeNamespace:null,

        //         nextSibling:null

        //         oldValue:null

        //         previousSibling:null

        //         removedNodes:NodeList[]

        //         target:body

        //         type:"attributes"

        //     }

        // ]

如果想在变化记录中保存属性原来的值可以将attributeOldValue属性设置为true

        let mutationAttr3 = new         MutationObserver((MutationRecords)=>console.log(MutationRecords.map((x)=>x.oldValue))        );

        mutationAttr3.observe(document.body,{attributeOldValue:true});

        document.body.setAttribute('foo','bar');

        document.body.setAttribute('foo','baz');

        document.body.setAttribute('foo','qux');

        //[null, 'bar', 'baz']

2、观察字符数据

        let mutationCharacterData1 = new         MutationObserver((MutationRecords)=>console.log(MutationRecords));

        //创建观察的文本节点

        document.body.firstChild.textContent='foo';

        mutationCharacterData1.observe(document.body.firstChild,{characterData:true});

        //赋值为相同的字符串

        document.body.firstChild.textContent='foo';

        //赋值为新字符串

        document.body.firstChild.textContent='bar';

        //通过节点设置函数赋值

        document.body.firstChild.textContent='baz';

        //以上变化都被记录下来了

        //[MutationRecord,MutationRecord,MutationRecord]

将characterData属性设置为true的默认行为不会在MutationRecord对象中记录原来的字符数据。如果想在变化记录中保存原来的字符数据可以将characterDataOldValue属性设置为true

        let mutationCharacterData2 = new         MutationObserver((MutationRecords)=>console.log(MutationRecords.map((x)=>x.oldValue))        );

        //创建观察的文本节点

        document.body.firstChild.textContent='foo';

        mutationCharacterData2.observe(document.body.firstChild,{characterDataOldValue:true});

        //赋值为相同的字符串

        document.body.firstChild.textContent='foo';

        //赋值为新字符串

        document.body.firstChild.textContent='bar';

        //通过节点设置函数赋值

        document.body.firstChild.textContent='baz';

        //每次变化都保留了上一次的值

        //['foo', 'foo', 'bar']

3、观察子节点

MutationObserver可以观察目标节点子节点的添加和移除。要观査子节点,需要在MutationObserverInit对象中将childList属性设置为true

例:添加子节点

        let mutationChildList1 = new         MutationObserver((MutationRecords)=>console.log(MutationRecords));

        mutationChildList1.observe(document.body,{childList:true});

        let div = document.createElement('div');

        document.body.appendChild(div);

        // [

        //     {

        //         addedNodes:NodeList[div],

        //         attributeName:null,

        //         attributeNamespace:null,

        //         nextSibling:null

        //         oldValue:null

        //         previousSibling:null

        //         removedNodes:NodeList[]

        //         target:body

        //         type:"childList"

        //     }

        // ]

例:移除子节点

在以上例子的基础上移除div

document.body.removeChild(div)

        // [

        //     {

        //         addedNodes:NodeList[],

        //         attributeName:null,

        //         attributeNamespace:null,

        //         nextSibling:null

        //         oldValue:null

        //         previousSibling:null

        //         removedNodes:NodeList[div]

        //         target:body

        //         type:"childList"

        //     }

        // ]

对子节点重新排序(尽管调用一个方法即可实现)会报告两次变化事件,因为从技术上会执行先移除再增加

        let mutationChildList2 = new         MutationObserver((MutationRecords)=>console.log(MutationRecords));

        //创建两个初始子节点

        document.body.appendChild(document.createElement('div'));

        document.body.appendChild(document.createElement('span'));

        mutationChildList2.observe(document.body,{childList:true});

        //交换子节点顺序

        document.body.insertBefore(document.body.lastChild,document.body.firstChild)

        //第一次是节点被删除,第二次是节点被添加

        // [

        //     {

        //         addedNodes:NodeList[],

        //         attributeName:null,

        //         attributeNamespace:null,

        //         nextSibling:null

        //         oldValue:null

        //         previousSibling:div

        //         removedNodes:NodeList[span]

        //         target:body

        //         type:"childList"

        //     }

        // ]

        // [

        //     {

        //         addedNodes:NodeList[span],

        //         attributeName:null,

        //         attributeNamespace:null,

        //         nextSibling:div

        //         oldValue:null

        //         previousSibling:null

        //         removedNodes:NodeList[]

        //         target:body

        //         type:"childList"

        //     }

        // ]

4、观察子树

默认情况下,MutationObserver将观察的范围限定为一个元素及其子节点的变化。可以把观察的范围扩展到这个元素的子树(所有后代的节点),这需要在MutationObserverInit对象中subtree属性设置为true

例:观察元素及其后代节点属性的变化

        let mutationObserver = new         MutationObserver((MutationRecords)=>console.log(MutationRecords));

        //创建一个后代

        document.body.appendChild(document.createElement('div'));

        //观察body元素及其子树

        mutationObserver.observe(document.body,{attributes:true,subtree:true});

        //修改body元素的子树

        document.body.firstChild.setAttribute('foo','bar')

        //[

        //     {

        //         addedNodes:NodeList[],

        //         attributeName:'foo',

        //         attributeNamespace:null,

        //         nextSibling:null

        //         oldValue:null

        //         previousSibling:null

        //         removedNodes:NodeList[]

        //         target:div

        //         type:"childList"

        //     }

        // ]

takeRecords()方法

takeRecord()方法可以清空记录队列,取出并返回其中所有的MutationRecord实例

例:

let observer = new MutationObser=((mutationRecords)=>console.log(mutationRecords));

observer.observe(document.body, { attributes: true });

document.body.className='foo';

document.body.className='bar';

document.body.className='baz';

console.log(observer.takeRecord());

console.log(observer.takeRecord());

//[MutationRecord, MutationRecord, MutationRecord]

//[]

此方法在希望断开与观察目标的联系,但又希望处理由于调用disconnect()而抛弃的记录队列中的MutationRecord实例时比较实用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值