-
-
Save pwFoo/13a17bda2f3e2160d6fd042fb3fe1987 to your computer and use it in GitHub Desktop.
MutationObserver vs. Proxy to detect .textContent changes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- | |
This demo shows two ways to detect changes to a DOM node `.textContent`, one | |
using a `MutationObserver` and the other using an ES2015 `Proxy`. | |
From testing, a `Proxy` appears to be 6-8x faster than using a MO in Chrome 50. | |
**Update**: removing the `Proxy` altogether speeds up the MO to be inline with the Proxy. | |
This has something to do with how the browser queues/prioritizes Proxies over MO. | |
Why is this useful? One could imagine creating a primative data-binding system | |
around the `Proxy` approach or using it to [polyfill `Object.observer()`](https://gist.github.com/ebidel/1b553d571f924da2da06). | |
Run it: http://jsbin.com/dukuluwufa/edit?html,output | |
--> | |
<p><button onclick="update()">update .textContent</button></p> | |
<p>[MO]'d node content: <span id="source"></span></p> | |
<p>[Proxy]'d node content: <span id="source-proxied"></span></p> | |
<output></output> | |
<script> | |
let start, finish, start2, finish2; | |
// Watch accesses/sets on a DOM element property. | |
function watchPropsOn(el, prop, callback=null) { | |
return new Proxy(el, { | |
set(target, propKey, value, receiver) { | |
if (prop === propKey) { | |
let finish2 = performance.now(); | |
out.innerHTML += `Proxy took: ${finish2 - start2}ms<br>`; | |
} | |
console.log(`Proxy set .${propKey} to ${value}`); | |
target[propKey] = value; | |
} | |
}); | |
} | |
function observe(target) { | |
// create an observer instance | |
let observer = new MutationObserver(mutations => { | |
let finish = performance.now(); | |
out.innerHTML += `MutationObserver took: ${finish - start}ms<br>`; | |
mutations.forEach(mutation => { | |
if (mutation.addedNodes.length) { | |
console.log(`MutationObserver observed childList as ${target.textContent}`) | |
} | |
}); | |
}); | |
observer.observe(target, {childList: true}); | |
} | |
function update() { | |
out.innerHTML = ''; | |
start = start2 = performance.now(); | |
proxy.textContent = source.textContent = Math.random(); | |
} | |
let source = document.querySelector('#source'); | |
let proxiedSource = document.querySelector('#source-proxied'); | |
let out = document.querySelector('output'); | |
observe(source); // setup MO | |
let proxy = watchPropsOn(proxiedSource, 'textContent'); // setup proxy. | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment