Mutation observer javascript

Author: s | 2025-04-24

★★★★☆ (4.5 / 3342 reviews)

wbcn boston

Simple mutation observer example in JavaScript doesn't work. 37 MutationObserver not working. 1 Mutations-Observer get added element. 2 Mutation observer This is where Mutation Observer comes into play. Mutation Observer is a JavaScript API that allows you to detect and respond to changes in the DOM. With Mutation

Download foglamp

Mutation Observer in JavaScript in Hindi

Reading Time: 5 minutesSometimes you may run into a challenging situation: You want some JavaScript to execute, but only if some other element has changed. At work, we’ve recently run into a situation with this kind of challenge. We’re using a library on videos, but how can we make sure that our JavaScript only runs after the video library runs? Well, we do it by mixing two really cool technologies: MutationObserver and Promise.Learning the MutationObserverSo what is a MutationObserver ?It’s an interface that allows you to observe a mutation in the DOM1. It’s a way to find out if elements have changed. We can discover if the element has gotten new attributes, or if it’s had child elements added or removed. So that makes this super handy for those situations when things out of our control are messing with our DOM.First, make an observerlet’s suppose you have a video, and you want to know if that video gets any new attributes added to it. First, we make a new observer.const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { console.log(mutation); // do something! });});A few things to note here:The argument passed in to your new MutationObserver is a callbackYou will need to iterate over the mutations to find the mutations you wantSecond, make a configurationBefore we start observing anything, we need to give some instructions on what to observe. You have a pretty good selection on how to configure your observer. With the exception of attributeFilter, all of these are boolean values, useful for answering questions you may have about the element:childListHave elements been added/removed directly in this element?attributesHas the element had any changes to attributes?characterDataHas any text inside of the element changed?subtreeHave elements more than one level deep changed?attributeOldValueDo you want the original value of the attribute?characterDataOldValueDo you want the original text of the element?attributeFilterWhat specific attributes should be watched?All we want to know is if a class name is changing. Easy enough!const observerConfig = { attributes: true, attributeOldValue: true};Next step: start observingWe’ve created the observer. We’ve created a configuration for it. Now, we just want to put it to useobserver.observe( document.querySelector('.myVideo'), observerConfig);We use the observe method, and pass in two arguments:Element to observeConfiguration to useBut it feels kinda weirdIf you’re thinking, “neat, but it feels weird,” you’re not alone. My long experience with JavaScript in the DOM tells me I should be able to do something like this:document .querySelector('.video') .addEventListener('mutation',mutationCallback)But, how would we be able to decide which mutations to watch (i.e. pass in a configuration)?¯_(ツ)_/¯Maybe that’s why it’s not an event to listen to on an element.And then the promiseSimply put, a promise is an object that may produce a single value at some time in the future2. I like to think of promises as an eventuality. Eventualities are events that will happen, but you don’t have the details of what happens. So a promise is a way to make sure that something always happens. This makes promises exceptionally helpful for AJAX. But it also makes them

Download repair video master

Master Mutation Observer In JavaScript:

MutationObserver的使用以及在Vue3中的使用案例MutationObserver 是一种浏览器提供的 API,可以在 DOM 的一部分改变时通知我们。在本博客中,我们将逐步讨论如何在常规 JavaScript 和 Vue3 中使用 MutationObserver,并提供一些实际使用案例。MutationObserver 介绍MutationObserver 是 JavaScript 中允许我们监视 DOM 变化的一种 API。当被观察的 DOM 中发生任何变化时,它就会通知我们。这可以帮助我们更轻松地处理动态 DOM 变化的情况。基本上,MutationObserver 类的实例用于对 DOM 文档进行监听,当被监听的 DOM 树内容发生任何变动时,包括子树的修改、节点属性的更改,或者文本内容的变化,都能及时触发回调函数。如何使用 MutationObserver在使用 MutationObserver 之前,我们首先需要创建一个新的 MutationObserver 实例。然后,我们需要指定一个回调函数作为其参数,该函数将在 DOM 改变时执行。var observer = new MutationObserver(callback);这个 callback 函数接收两个参数:一个是 mutations 数组,用于保存所有发生的变化的列表;另一个是观察者对象本身,可以用于停止或开始观察。function callback(mutations, observer) { mutations.forEach(mutation => { console.log(mutation); });}然后,我们需要选择要观察的 DOM 元素,并指定要观察的变化类型。observe() 方法接受两个参数:要观察的 DOM 节点和一个用于指定哪些变化将被观察的配置对象。var targetNode = document.getElementById('some-id');observer.observe(targetNode, { childList: true, subtree: true });在上述例子中,配置对象 { childList: true, subtree: true } 表示我们将观察到目标节点的子节点的变化,以及子节点树下的所有更深层次的变化。然后,我们可以禁用或启用观察器。例如,disconnect() 方法可以用来停止观察:observer.disconnect();再次启动观察,只需再次调用 observe() 方法。Vue3 中的使用案例在 Vue3 中使用 MutationObserver 与在普通 JavaScript 中使用 MutationObserver 相同。考虑到 Vue3 的一些新特性,实例使用可能会略有不同。看一下下面的例子:import { onMounted, onUnmounted } from 'vue';export default { setup() { const targetNode = document.getElementById('some-id'); const config = { childList: true, subtree: true }; const observer = new MutationObserver((mutations, observer) => { mutations.forEach(mutation => { console.log(mutation); }); }); onMounted(() => { observer.observe(targetNode, config); }); onUnmounted(() => { observer.disconnect(); }); },};在这个 Vue3 示例中,我们首先导入了 onMounted 和 onUnmounted 生命周期钩子。然后在 setup 函数中创建了一个 MutationObserver 实例。在组件加载完成(onMounted)时,我们开始对目标节点进行观察。然后,当组件卸载(onUnmounted)时,我们停止了观察。这样,就可以在 Vue3 组件中有效地使用 MutationObserver 来观察和响应 DOM 的变化。结论MutationObserver 是一个强大的 API,允许我们观察 DOM 的变化。无论是在普通的 JavaScript 中还是在 Vue3 中,都可以有效利用它来增强交互和动态响应。但请注意,尽管 MutationObserver 是一个有用的工具,却不应该过度使用它。过度监测 DOM 变化可能会导致性能问题。因此,使用时要根据真正需要来进行合理配置。前端妙妙屋 - 分享前端实战经验,点亮你的编程灯塔

Understanding Mutation Observer in JavaScript

But transparently wrapped by observable proxies. raw can access the original non-reactive object. Modifying and accessing properties on the raw object doesn't trigger reactions.Using raw at property access console.log(person.name));// this logs 'Bob'person.name = 'Bob';// `name` is used from the raw non-reactive object, this won't log anythingraw(person).name = 'John';">import { observable, observe, raw } from '@nx-js/observer-util';const person = observable();const logger = observe(() => console.log(person.name));// this logs 'Bob'person.name = 'Bob';// `name` is used from the raw non-reactive object, this won't log anythingraw(person).name = 'John';Using raw at property mutation console.log(`${person.name}: ${raw(person).age}`));// this logs 'Bob: 20'person.name = 'Bob';// `age` is used from the raw non-reactive object, this won't log anythingperson.age = 33;">import { observable, observe, raw } from '@nx-js/observer-util';const person = observable({ age: 20 });observe(() => console.log(`${person.name}: ${raw(person).age}`));// this logs 'Bob: 20'person.name = 'Bob';// `age` is used from the raw non-reactive object, this won't log anythingperson.age = 33;Platform supportNode: 6.5 and aboveChrome: 49 and aboveFirefox: 38 and aboveSafari: 10 and aboveEdge: 12 and aboveOpera: 36 and aboveIE is not supportedAlternative buildsThis library detects if you use ES6 or commonJS modules and serve the right format to you. The exposed bundles are transpiled to ES5 to support common tools - like UglifyJS minifying. If you would like a finer control over the provided build, you can specify them in your imports.@nx-js/observer-util/dist/es.es6.js exposes an ES6 build with ES6 modules.@nx-js/observer-util/dist/es.es5.js exposes an ES5 build with ES6 modules.@nx-js/observer-util/dist/cjs.es6.js exposes an ES6 build with commonJS modules.@nx-js/observer-util/dist/cjs.es5.js exposes an ES5 build with commonJS modules.If you use a bundler, set up an alias for @nx-js/observer-util to point to your desired build. You can learn how to do it with webpack here and with rollup here.ContributingContributions are always welcomed! Just send a PR for fixes and doc updates and open issues for new features beforehand. Make sure that the tests and the. Simple mutation observer example in JavaScript doesn't work. 37 MutationObserver not working. 1 Mutations-Observer get added element. 2 Mutation observer

Mutation Observer in JavaScript - YouTube

Exploring DOM Changes: Live Examples with Mutation Observers Watch this space for changes! Add New Element and Change Color // Get the element to observe const targetNode = document.getElementById('target'); // Define configurations for the observer const config = { attributes: true, childList: true, subtree: true, attributeOldValue: true }; // Callback function to execute when mutations are observed const callback = function(mutationsList, observer) { for (const mutation of mutationsList) { const message = document.createElement('p'); if (mutation.type === 'childList') { message.textContent = 'A child node has been added or removed.'; message.style.color = 'green'; } else if (mutation.type === 'attributes') { message.textContent = 'The ' + mutation.attributeName + ' attribute was modified.'; message.style.color = 'blue'; } document.getElementById('log').appendChild(message); } }; // Create an observer instance linked to the callback function const observer = new MutationObserver(callback); // Start observing the target node for configured mutations observer.observe(targetNode, config); // Function to add new elements function addNewElement() { const newElement = document.createElement('div'); newElement.textContent = 'New element added!'; targetNode.appendChild(newElement); } // Function to change attributes function changeAttribute() { const currentColor = targetNode.style.backgroundColor; targetNode.style.backgroundColor = currentColor === 'lightgray' ? 'lightblue' : 'lightgray'; } "> Source Code: (back to article) Result: Report an issue

javascript - Mutation observer not observing element when

Useful when you are expecting a DOM change.The promise basicsAt the most basic form, a promise needs to know when something is resolved, and when something is rejected. What you’re looking for is the means to a .then() or .catch() method. Those two little guys are your eventualities.Start with your end goal in mindPart of my own personal struggle with understanding promises is that I think I start in the wrong direction. I start from the promise instead of what I want to do. So, if you’re new to promises, and/or curious how we can use them with mutation observers, let’s go ahead and say that this is our end goal:attributePromise(document.querySelector('video'), 'class').then((element)=> { // do something because the video's classname attribute changed}).catch((element)=> { // do something because the video never got a class name change});Begin with the wrapper functionStarting from the back, we know we want to make a function that takes an element and an attribute name as two separate arguments. So we’re looking for something like this:function attributePromise(element,attributeName) { return new Promise((resolve,reject) => { });}Add your MutationObserverWe’ll throw in the observer we’ve already learned about, and its configuration. It just doesn’t quite seem like we’ve reached the finish line yet, though. For one thing, we need to actually loop through the mutation, and see if it’s…mutated.For another, what if it never changes? How do we account for the scenario where the element never changes at all?function attrPromise(element, attributeName) { return new Promise((resolve,reject) => { const observerConfig = {attributes: true,attributeOldValue:true}; const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { // uhhh... stuff will go here? }); }); observer.observe(element, observerConfig); });}Add some timed rejectionWhat we’ll do is make a variable called hasChanged, and we’ll set it to false. Then, we’ll throw a timer that will check every 500ms to see if that hasChanged is true.function attributePromise(element, attributeName) { const rejectTime = 500; return new Promise((resolve,reject) => { let hasChanged = false; const observerConfig = {attributes: true,attributeOldValue:true}; const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { }); }); window.setTimeout(()=>;{ if (!hasChanged) { reject(element); } },rejectTime); observer.observe(element, observerConfig); });}Then, check your mutantsNow we get into into the forEach() loop. What we want to do is compare mutation.attributeName to the attributeName that’s been provided as an argument.If the two match, we’ll do three things:Set hasChanged to true so that our timer can take a breatherDisconnect the observer because we don’t need it any moreResolve the promisefunction attrPromise(element, attributeName) { const rejectTime = 500; return new Promise((resolve,reject) => { let hasChanged = false; const observerConfig = {attributes: true,attributeOldValue:true}; const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.attributeName == attributeName) { hasChanged = true; observer.disconnect(); resolve(element, element.getAttribute(attributeName)); } }); }); window.setTimeout(()=>{ if (!hasChanged) { reject(element); } },rejectTime); observer.observe(element, observerConfig); });}Get off the Happy PathSo far, we’ve written a “happy path” Mutation Promise. Meaning that attributeName will always be an argument that’s been provided, and you’ll always want it to eventually reject. But, let’s go off the happy path by adding

Mutation observer - The Modern JavaScript Tutorial

Some flexibility to our function.We’ll set a rejectTime with a default value of zero, and then add a setTimeout any time it’s greater than zero.We’ll also modify our conditions inside of the forEach(). One condition will account for us having an attributeName AND that attributeName changing. Another will account for the scenario where we didn’t send in an attributeName at all.function attrPromise(element, attributeName, rejectTime = 0) { return new Promise((resolve,reject) => { let hasChanged = false; const observerConfig = {attributes: true,attributeOldValue:true}; const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (attributeName && mutation.attributeName == attributeName) { hasChanged = true; observer.disconnect(); resolve(element, element.getAttribute(attributeName)); } if (!attributeName) { hasChanged = true; observer.disconnect(); resolve(element); } }); }); if (rejectTime > 0) { window.setTimeout(()=>{ if (!hasChanged) { reject(element); } },rejectTime * 100); } if (attributeName) observerConfig.attributeFilter = [attributeName]; observer.observe(element, observerConfig); });}Link(s) or it Didn’t HappenThe raw code is in a gist for your convenience.But if you want an example of this in action, there’s a codepen for that. Click the button, or don’t.See the Pen Mutation Promise by Paceaux (@paceaux) on CodePen.

Mutation Observer in JavaScript. Introduction - Medium

And in my simple little mind, I figured, I don't care. If something changes, just rerun the count to count images.Look at that code and see if you can figure out the issue. If you can, leave me a comment below.So yes, this "worked", but this is what happened:I clicked the button to add a new imageThe mutation observer fired and was like, cool, new shit to do, run renderCountrenderCount got the images and updated the HTML to reflect the new countHey guess what, renderCount changed the DOM tree, let's run the observer againRepeat until the heat death of the universeI had to tweak things a bit, but here's the final version, and I'll explain what I did:class ImgCounter extends HTMLElement { #myObserver; constructor() { super(); } connectedCallback() { // create the div we'll use to monitor images: this.innerHTML += ''; this.renderCount(); const mutationObserver = (mutationList, observer) => { for(const m of mutationList) { if(m.target === this) { this.renderCount(); } } }; this.myObserver = new MutationObserver(mutationObserver); this.myObserver.observe(this, { childList: true, subtree: true }); } disconnectedCallback() { this.myObserver.disconnect(); } renderCount() { let imgs = this.querySelectorAll('img'); this.querySelector('#imgcountertext').innerHTML = `There are ${imgs.length} images in me.`; }}if(!customElements.get('img-counter')) customElements.define('img-counter', ImgCounter);document.querySelector('#testAdd').addEventListener('click', () => { document.querySelector('img-counter').innerHTML = 'New: ' + document.querySelector('img-counter').innerHTML;});I initially had said I didn't care about what was in the list of items changed in the mutation observer, but I noticed that the target value was different when I specifically added my image count report. To help with this, I'm now using a div tag with an ID and renderCount modifies that.When a new image (or anything) is added directly inside the component, my target value is img-counter, or this, which means I can run renderCount on it. When renderCount runs, the target of the mutation is its own div.Also, I noticed that the MutationObserver talks specifically called out the disconnect method as a way of ending the DOM observation. That feels pretty important, and web components make it easy with the disconnectedCallback method.All in all, it works well now (as far as I know ;), and you can test it yourself below: See the Pen Img Counter WC 2 by Raymond Camden (@cfjedimaster) on CodePen.Remember, MutationObserver can absolutely be used outside of web components. Also note that if you only want to respond to an attribute change in a web component, that's really easy as it's baked into the spec. As always, let me. Simple mutation observer example in JavaScript doesn't work. 37 MutationObserver not working. 1 Mutations-Observer get added element. 2 Mutation observer This is where Mutation Observer comes into play. Mutation Observer is a JavaScript API that allows you to detect and respond to changes in the DOM. With Mutation

bootp download

Mutation Observer - JavaScript - SitePoint Forums

That implements the Subject interface: // Subjectclass Store implements Subject {} Next, initialize the Subject’s state in the Store class. The subject’s observers will react to changes to this state. In this case, the state is a number, and the observers will react to an increase in the number: // Subject stateprivate numberOfProducts: number; Next, initialize an array of observers. This array is how you'll keep track of the observers: // initializing observersprivate observers: Observer[] = []; You might find some implementations of the observer pattern using a Set data structure in place of an array to keep track of the observer. Using a Set will ensure that the same observer won’t appear twice. If you want to use an array instead, you should check for duplicate observers in your attach method. Next, you should implement the Subject’s methods—attach, detach, and notify/update—in your concrete class. To implement the attach method, first check if the observer is already attached and throw an error if it is. Otherwise, add the observer to the array using the JavaScript array method, push: // Attaching Observer(s)attachObserver(observer: Observer): void { // Check if the observer has already been attached const observerExists = this.observers.includes(observer); if (observerExists) { throw new Error('Observer has already been subscribed '); } // Add a new observer this.observers.push(observer);} Next, implement your detach method by finding the index and removing it from the array using the JavaScript splice method. There can be scenarios where the observer you are trying to detach has already been detached or was not subscribed in the first place. You should handle these scenarios by adding a conditional statement to check if the observer is in the array or the set as the case may be. // Detaching Observer(s)detachObserver(observer: Observer): void { console.log(`Detaching observer ${JSON.stringify(observer)}`); const observerIndex = this.observers.indexOf(observer); if

mutation observers - Javascript: mutationobserver is not alerting

A design pattern is a template that solves a commonly recurring problem in software design. The observer pattern, also known as the publish-subscribe pattern, is a behavioral pattern. It allows you to notify multiple objects or subscribers about any event that is published in the object they’re observing. Here you will learn how to implement the observer design pattern in TypeScript. The Observer Pattern The observer pattern works by defining a one-to-many relationship between the publisher and its subscribers. When an event occurs in the publisher, it will notify all subscribers to that event. One widespread example of this pattern is JavaScript event listeners. For context, assume you’re building an inventory tracker that keeps track of the number of products in your store. In this case, your store is the subject/publisher, and your inventory is the observer/subscriber. Using the observer design pattern would be optimal in this situation. In the observer design pattern, your subject class must implement three methods: An attach method. This method adds an observer to the subject. A detach method. This method removes an observer from a subject. A notify/update method. This method notifies the subject’s observers when the state changes in the subject. Your observer class must implement one method, the update method. This method reacts when there’s a change in its subject’s state. Implementing the Subject and Observer Classes The first step to implementing this pattern is to create interfaces for the subject and observer class, to ensure that they implement the correct methods: // Subject/Publisher Interfaceinterface Subject { attachObserver(observer: Observer): void; detachObserver(observer: Observer): void; notifyObserver(): void;} // Observer/Subscriber Interfaceinterface Observer { update(subject: Subject): void;} The interfaces in the code block above define the methods your concrete classes must implement. A Concrete Subject Class The next step is to implement a concrete subject class. Simple mutation observer example in JavaScript doesn't work. 37 MutationObserver not working. 1 Mutations-Observer get added element. 2 Mutation observer

Understanding Mutation Observer in JavaScript - Zerosack

Hire Me! I'm currently looking for my next role in developer relations and advocacy. If you've got an open role and think I'd be a fit, please reach out. You can also find me on LinkedIn. While driving my kids to school this morning, I had an interesting thought. Is it possible for a web component to recognize, and respond, when its inner DOM contents have changed? Turns out of course it is, and the answer isn't really depenedant on web components, but is a baked-in part of the web platform, the MutationObserver. Here's what I built as a way to test it out.The Initial Web ComponentI began with a simple web component that had the following simple feature - count the number of images inside it and report. So we can start with this HTML: And build a simple component:class ImgCounter extends HTMLElement { constructor() { super(); } connectedCallback() { let imgs = this.querySelectorAll('img'); this.innerHTML += `There are ${imgs.length} images in me.`; } }if(!customElements.get('img-counter')) customElements.define('img-counter', ImgCounter);It just uses querySelectorAll to count the img node inside it. For my initial HTML, this reports 3 of course.I then added a simple button to my HTML:Add ImgAnd a bit of code:document.querySelector('#testAdd').addEventListener('click', () => { document.querySelector('img-counter').innerHTML = 'New: ' + document.querySelector('img-counter').innerHTML;});When run, it will add a new image, but obviously, the counter won't update. Here's a CodePen of this initial version: See the Pen Img Counter WC 1 by Raymond Camden (@cfjedimaster) on CodePen.Enter - the MutationObserverThe MDN docs on MutationObserver are pretty good, as always. I won't repeat what's written there but the basics are:Define what you want to observe under a DOM element - which includes the subtree, childList, and attributesWrite your callbackDefine the observer based on the callbackTie the observer to the DOM root you want to watchSo my thinking was...Move out my 'count images and update display' to a functionAdd a mutation observer and when things change, re-run the new functionMy first attempt was rather naive, but here it is in code form, not CodePen, for reasons that will be clear soon:class ImgCounter extends HTMLElement { constructor() { super(); } connectedCallback() { this.renderCount(); const mutationObserver = (mutationList, observer) => { this.renderCount(); }; const observer = new MutationObserver(mutationObserver); observer.observe(this, { childList: true, subtree: true }); } renderCount() { let imgs = this.querySelectorAll('img'); this.innerHTML += `There are ${imgs.length} images in me.`; }}So the MutationObserver callback is sent information about what changed,

Comments

User5899

Reading Time: 5 minutesSometimes you may run into a challenging situation: You want some JavaScript to execute, but only if some other element has changed. At work, we’ve recently run into a situation with this kind of challenge. We’re using a library on videos, but how can we make sure that our JavaScript only runs after the video library runs? Well, we do it by mixing two really cool technologies: MutationObserver and Promise.Learning the MutationObserverSo what is a MutationObserver ?It’s an interface that allows you to observe a mutation in the DOM1. It’s a way to find out if elements have changed. We can discover if the element has gotten new attributes, or if it’s had child elements added or removed. So that makes this super handy for those situations when things out of our control are messing with our DOM.First, make an observerlet’s suppose you have a video, and you want to know if that video gets any new attributes added to it. First, we make a new observer.const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { console.log(mutation); // do something! });});A few things to note here:The argument passed in to your new MutationObserver is a callbackYou will need to iterate over the mutations to find the mutations you wantSecond, make a configurationBefore we start observing anything, we need to give some instructions on what to observe. You have a pretty good selection on how to configure your observer. With the exception of attributeFilter, all of these are boolean values, useful for answering questions you may have about the element:childListHave elements been added/removed directly in this element?attributesHas the element had any changes to attributes?characterDataHas any text inside of the element changed?subtreeHave elements more than one level deep changed?attributeOldValueDo you want the original value of the attribute?characterDataOldValueDo you want the original text of the element?attributeFilterWhat specific attributes should be watched?All we want to know is if a class name is changing. Easy enough!const observerConfig = { attributes: true, attributeOldValue: true};Next step: start observingWe’ve created the observer. We’ve created a configuration for it. Now, we just want to put it to useobserver.observe( document.querySelector('.myVideo'), observerConfig);We use the observe method, and pass in two arguments:Element to observeConfiguration to useBut it feels kinda weirdIf you’re thinking, “neat, but it feels weird,” you’re not alone. My long experience with JavaScript in the DOM tells me I should be able to do something like this:document .querySelector('.video') .addEventListener('mutation',mutationCallback)But, how would we be able to decide which mutations to watch (i.e. pass in a configuration)?¯_(ツ)_/¯Maybe that’s why it’s not an event to listen to on an element.And then the promiseSimply put, a promise is an object that may produce a single value at some time in the future2. I like to think of promises as an eventuality. Eventualities are events that will happen, but you don’t have the details of what happens. So a promise is a way to make sure that something always happens. This makes promises exceptionally helpful for AJAX. But it also makes them

2025-04-22
User1032

MutationObserver的使用以及在Vue3中的使用案例MutationObserver 是一种浏览器提供的 API,可以在 DOM 的一部分改变时通知我们。在本博客中,我们将逐步讨论如何在常规 JavaScript 和 Vue3 中使用 MutationObserver,并提供一些实际使用案例。MutationObserver 介绍MutationObserver 是 JavaScript 中允许我们监视 DOM 变化的一种 API。当被观察的 DOM 中发生任何变化时,它就会通知我们。这可以帮助我们更轻松地处理动态 DOM 变化的情况。基本上,MutationObserver 类的实例用于对 DOM 文档进行监听,当被监听的 DOM 树内容发生任何变动时,包括子树的修改、节点属性的更改,或者文本内容的变化,都能及时触发回调函数。如何使用 MutationObserver在使用 MutationObserver 之前,我们首先需要创建一个新的 MutationObserver 实例。然后,我们需要指定一个回调函数作为其参数,该函数将在 DOM 改变时执行。var observer = new MutationObserver(callback);这个 callback 函数接收两个参数:一个是 mutations 数组,用于保存所有发生的变化的列表;另一个是观察者对象本身,可以用于停止或开始观察。function callback(mutations, observer) { mutations.forEach(mutation => { console.log(mutation); });}然后,我们需要选择要观察的 DOM 元素,并指定要观察的变化类型。observe() 方法接受两个参数:要观察的 DOM 节点和一个用于指定哪些变化将被观察的配置对象。var targetNode = document.getElementById('some-id');observer.observe(targetNode, { childList: true, subtree: true });在上述例子中,配置对象 { childList: true, subtree: true } 表示我们将观察到目标节点的子节点的变化,以及子节点树下的所有更深层次的变化。然后,我们可以禁用或启用观察器。例如,disconnect() 方法可以用来停止观察:observer.disconnect();再次启动观察,只需再次调用 observe() 方法。Vue3 中的使用案例在 Vue3 中使用 MutationObserver 与在普通 JavaScript 中使用 MutationObserver 相同。考虑到 Vue3 的一些新特性,实例使用可能会略有不同。看一下下面的例子:import { onMounted, onUnmounted } from 'vue';export default { setup() { const targetNode = document.getElementById('some-id'); const config = { childList: true, subtree: true }; const observer = new MutationObserver((mutations, observer) => { mutations.forEach(mutation => { console.log(mutation); }); }); onMounted(() => { observer.observe(targetNode, config); }); onUnmounted(() => { observer.disconnect(); }); },};在这个 Vue3 示例中,我们首先导入了 onMounted 和 onUnmounted 生命周期钩子。然后在 setup 函数中创建了一个 MutationObserver 实例。在组件加载完成(onMounted)时,我们开始对目标节点进行观察。然后,当组件卸载(onUnmounted)时,我们停止了观察。这样,就可以在 Vue3 组件中有效地使用 MutationObserver 来观察和响应 DOM 的变化。结论MutationObserver 是一个强大的 API,允许我们观察 DOM 的变化。无论是在普通的 JavaScript 中还是在 Vue3 中,都可以有效利用它来增强交互和动态响应。但请注意,尽管 MutationObserver 是一个有用的工具,却不应该过度使用它。过度监测 DOM 变化可能会导致性能问题。因此,使用时要根据真正需要来进行合理配置。前端妙妙屋 - 分享前端实战经验,点亮你的编程灯塔

2025-04-13
User7835

Exploring DOM Changes: Live Examples with Mutation Observers Watch this space for changes! Add New Element and Change Color // Get the element to observe const targetNode = document.getElementById('target'); // Define configurations for the observer const config = { attributes: true, childList: true, subtree: true, attributeOldValue: true }; // Callback function to execute when mutations are observed const callback = function(mutationsList, observer) { for (const mutation of mutationsList) { const message = document.createElement('p'); if (mutation.type === 'childList') { message.textContent = 'A child node has been added or removed.'; message.style.color = 'green'; } else if (mutation.type === 'attributes') { message.textContent = 'The ' + mutation.attributeName + ' attribute was modified.'; message.style.color = 'blue'; } document.getElementById('log').appendChild(message); } }; // Create an observer instance linked to the callback function const observer = new MutationObserver(callback); // Start observing the target node for configured mutations observer.observe(targetNode, config); // Function to add new elements function addNewElement() { const newElement = document.createElement('div'); newElement.textContent = 'New element added!'; targetNode.appendChild(newElement); } // Function to change attributes function changeAttribute() { const currentColor = targetNode.style.backgroundColor; targetNode.style.backgroundColor = currentColor === 'lightgray' ? 'lightblue' : 'lightgray'; } "> Source Code: (back to article) Result: Report an issue

2025-04-17
User2440

Useful when you are expecting a DOM change.The promise basicsAt the most basic form, a promise needs to know when something is resolved, and when something is rejected. What you’re looking for is the means to a .then() or .catch() method. Those two little guys are your eventualities.Start with your end goal in mindPart of my own personal struggle with understanding promises is that I think I start in the wrong direction. I start from the promise instead of what I want to do. So, if you’re new to promises, and/or curious how we can use them with mutation observers, let’s go ahead and say that this is our end goal:attributePromise(document.querySelector('video'), 'class').then((element)=> { // do something because the video's classname attribute changed}).catch((element)=> { // do something because the video never got a class name change});Begin with the wrapper functionStarting from the back, we know we want to make a function that takes an element and an attribute name as two separate arguments. So we’re looking for something like this:function attributePromise(element,attributeName) { return new Promise((resolve,reject) => { });}Add your MutationObserverWe’ll throw in the observer we’ve already learned about, and its configuration. It just doesn’t quite seem like we’ve reached the finish line yet, though. For one thing, we need to actually loop through the mutation, and see if it’s…mutated.For another, what if it never changes? How do we account for the scenario where the element never changes at all?function attrPromise(element, attributeName) { return new Promise((resolve,reject) => { const observerConfig = {attributes: true,attributeOldValue:true}; const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { // uhhh... stuff will go here? }); }); observer.observe(element, observerConfig); });}Add some timed rejectionWhat we’ll do is make a variable called hasChanged, and we’ll set it to false. Then, we’ll throw a timer that will check every 500ms to see if that hasChanged is true.function attributePromise(element, attributeName) { const rejectTime = 500; return new Promise((resolve,reject) => { let hasChanged = false; const observerConfig = {attributes: true,attributeOldValue:true}; const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { }); }); window.setTimeout(()=>;{ if (!hasChanged) { reject(element); } },rejectTime); observer.observe(element, observerConfig); });}Then, check your mutantsNow we get into into the forEach() loop. What we want to do is compare mutation.attributeName to the attributeName that’s been provided as an argument.If the two match, we’ll do three things:Set hasChanged to true so that our timer can take a breatherDisconnect the observer because we don’t need it any moreResolve the promisefunction attrPromise(element, attributeName) { const rejectTime = 500; return new Promise((resolve,reject) => { let hasChanged = false; const observerConfig = {attributes: true,attributeOldValue:true}; const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.attributeName == attributeName) { hasChanged = true; observer.disconnect(); resolve(element, element.getAttribute(attributeName)); } }); }); window.setTimeout(()=>{ if (!hasChanged) { reject(element); } },rejectTime); observer.observe(element, observerConfig); });}Get off the Happy PathSo far, we’ve written a “happy path” Mutation Promise. Meaning that attributeName will always be an argument that’s been provided, and you’ll always want it to eventually reject. But, let’s go off the happy path by adding

2025-04-09
User3636

And in my simple little mind, I figured, I don't care. If something changes, just rerun the count to count images.Look at that code and see if you can figure out the issue. If you can, leave me a comment below.So yes, this "worked", but this is what happened:I clicked the button to add a new imageThe mutation observer fired and was like, cool, new shit to do, run renderCountrenderCount got the images and updated the HTML to reflect the new countHey guess what, renderCount changed the DOM tree, let's run the observer againRepeat until the heat death of the universeI had to tweak things a bit, but here's the final version, and I'll explain what I did:class ImgCounter extends HTMLElement { #myObserver; constructor() { super(); } connectedCallback() { // create the div we'll use to monitor images: this.innerHTML += ''; this.renderCount(); const mutationObserver = (mutationList, observer) => { for(const m of mutationList) { if(m.target === this) { this.renderCount(); } } }; this.myObserver = new MutationObserver(mutationObserver); this.myObserver.observe(this, { childList: true, subtree: true }); } disconnectedCallback() { this.myObserver.disconnect(); } renderCount() { let imgs = this.querySelectorAll('img'); this.querySelector('#imgcountertext').innerHTML = `There are ${imgs.length} images in me.`; }}if(!customElements.get('img-counter')) customElements.define('img-counter', ImgCounter);document.querySelector('#testAdd').addEventListener('click', () => { document.querySelector('img-counter').innerHTML = 'New: ' + document.querySelector('img-counter').innerHTML;});I initially had said I didn't care about what was in the list of items changed in the mutation observer, but I noticed that the target value was different when I specifically added my image count report. To help with this, I'm now using a div tag with an ID and renderCount modifies that.When a new image (or anything) is added directly inside the component, my target value is img-counter, or this, which means I can run renderCount on it. When renderCount runs, the target of the mutation is its own div.Also, I noticed that the MutationObserver talks specifically called out the disconnect method as a way of ending the DOM observation. That feels pretty important, and web components make it easy with the disconnectedCallback method.All in all, it works well now (as far as I know ;), and you can test it yourself below: See the Pen Img Counter WC 2 by Raymond Camden (@cfjedimaster) on CodePen.Remember, MutationObserver can absolutely be used outside of web components. Also note that if you only want to respond to an attribute change in a web component, that's really easy as it's baked into the spec. As always, let me

2025-04-17

Add Comment