-
Notifications
You must be signed in to change notification settings - Fork 375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Element.prototype.connectedCallback, et al. #629
Comments
|
This is how my base class currently implements // inside the base class:
observeChildren(this, this.childConnectedCallback, this.childDisconnectedCallback)
// outside the base class:
// NOTE: If a child is disconnected then connected to the same parent in the
// same turn, then the onConnect and onDisconnect callbacks won't be called
// because the DOM tree will be back in the exact state as before.
function observeChildren(ctx, onConnect, onDisconnect) {
const observer = new MutationObserver(changes => {
const weights = new Map
for (const change of changes) {
if (change.type != 'childList') continue
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 [node, weight] of weights)
if (weight > 0)
onConnect.call(ctx, node)
else if (weight < 0)
onDisconnect.call(ctx, node)
})
observer.observe(ctx, { childList: true })
return observer
} |
If we're dealing only with custom elements, then putting However, it won't work when the tree is mixed with native elements, because those never get There's probably other use cases for this. Overall, the main point is that if those methods were called on native elements, it would be more inline with the Extensible Web Manifesto, it would explain native elements better, and it would mean that the above "monkey patching" works because the new APIs explain existing elements, as in "native elements are implemented with things like |
Here's 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 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: 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 |
I made that point during one of F2Fs and we specially reached a consensus not to do this. |
Closing per consensus. |
Based on the extensible web manifesto, it seems that the following should work, but it doesn't:
(fiddle).
and similarly with
disconnectedCallback
,attributeChangedCallback
, etc.Shouldn't we be able to do stuff like that, assuming APIs like the Custom Elements API help to explain native elements?
It'd be nice for library authors to be able to hook into the engine like that.
The current alternative way to hook into the engine like that is to use MutationObserver on all elements in the page, but the above solution
The text was updated successfully, but these errors were encountered: