- From: Joseph Orbegoso Pea <notifications@github.com>
- Date: Sat, 11 Mar 2017 20:14:34 -0800
- To: w3c/webcomponents <webcomponents@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <w3c/webcomponents/issues/629/285921048@github.com>
Here's `childConnectedCallback` implemented on `Element.prototype.connectedCallback` (compare with the above `MutationObserver` implementation):
```js
Element.prototype.connectedCallback = function() {
if (this.parentElement && this.parentElement.childConnectedCallback)
this.parentElement.childConnectedCallback(this)
}
```
This is much simpler!
Also (at least in Chrome), the order of `MutationRecords` do not always fire in the same order as the things that trigger them. This sort of problem is completely avoided with the `Element.prototype.connectedCallback` implementation.
For reference, I discovered that using a single global MutationObserver rather than one per element fixes the problem of MutationRecord callbacks happening out of order. After changing my MutationObserver implementation to the following I solved a bug caused by out-of-order callbacks:
```js
let childObservationHandlers = null
let childObserver = null
function observeChildren(ctx, onConnect, onDisconnect) {
if (!childObservationHandlers) childObservationHandlers = new Map
if (!childObserver) childObserver = createChildObserver()
childObservationHandlers.set(ctx, {onConnect, onDisconnect})
childObserver.observe(ctx, { childList: true })
return true
}
function createChildObserver() {
return new MutationObserver(async (changes) => {
const weightsPerTarget = new Map
console.log('changes', changes, performance.now())
for (const change of changes) {
if (change.type != 'childList') continue
if (!weightsPerTarget.has(change.target))
weightsPerTarget.set(change.target, new Map)
const weights = weightsPerTarget.get(change.target)
for (const addedNode of change.addedNodes)
weights.set(addedNode, (weights.get(addedNode) || 0) + 1)
for (const removedNode of change.removedNodes)
weights.set(removedNode, (weights.get(removedNode) || 0) - 1)
}
for (const [target, weights] of weightsPerTarget) {
const {onConnect, onDisconnect} = childObservationHandlers.get(target)
for (const [node, weight] of weights) {
if (weight > 0 && typeof onConnect == 'function')
onConnect.call(target, node)
else if (weight < 0 && typeof onDisconnect == 'function')
onDisconnect.call(target, node)
}
}
})
}
```
And... now it is even *more* complicated than the 3-line `Element.prototype.connectedCallback` version.
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/w3c/webcomponents/issues/629#issuecomment-285921048
Received on Sunday, 12 March 2017 04:15:06 UTC