diff.js
In the file diff.js, the _lastDomChild is given newVNode._children[newVNode._children.length - 1]._dom
if (oldVNode.type === Fragment || newType === Fragment) {
diffChildren(parentDom, newVNode, oldVNode, context, isSvg, excessDomChildren, mounts, c);
if (newVNode._children.length) {
dom = newVNode._children[0]._dom;
newVNode._lastDomChild = newVNode._children[newVNode._children.length - 1]._dom;
}
}
diffchildren.js
It doesn't seem to be used
if (childVNode._lastDomChild != null) {
newDom = childVNode._lastDomChild;
}
else if (excessDomChildren == oldVNode || newDom != childDom || newDom.parentNode == null) {
// ....
}
I am learning the source code of preact锛宼hank you
That's a great question! The property _lastDomChild is used for Fragments. Each vnode has a _dom property which denotes the first child node of a given vnode. With Fragments there will be a different relationship between the DOM and a vnode.
That 1:1 mapping doesn't hold true for them anymore and we chose _lastDomChild as a pointer to the last child node of a vnode. This becomes more important when there are nested or sibling Fragments at play. In these cases we need to be very aware of our current position to modify the DOM at the correct place.
// Sibling Fragments
<div>
<Fragment>foo</Fragment>
<Fragment>bar</Fragment>
<span>bob</span>
</div>
// Nested Fragments
<div>
<Fragment>
<Fragment>
<div>foo</div>
</Fragment>
</Fragment>
</div>
Typically there are lots of cases in real world apps where both scenarios are used together. That said, our current reconciler (what's in diffChildren()) needs to be switched to diff based on the index in the children array instead of getting the correct child by traversing the DOM. In current code where checking for newDom in the line you posted above and use it to compare the current childDom against it.
We believe that this is necessary to fix the remaining issues with Fragments. It's something on our todo list and that we have a few branches where we experimented with, but we're waiting for #1440 to be merged to tackle it.
Besides the JSDoc comments we have a few hints in our internal typings (usually internal.d.ts) about the use of each property.
Hope this helps to get you started :)
Most helpful comment
That's a great question! The property
_lastDomChildis used forFragments. Eachvnodehas a_domproperty which denotes the first child node of a givenvnode. WithFragmentsthere will be a different relationship between the DOM and avnode.That 1:1 mapping doesn't hold true for them anymore and we chose
_lastDomChildas a pointer to the last child node of avnode. This becomes more important when there are nested or siblingFragmentsat play. In these cases we need to be very aware of our current position to modify the DOM at the correct place.Typically there are lots of cases in real world apps where both scenarios are used together. That said, our current reconciler (what's in
diffChildren()) needs to be switched to diff based on the index in the children array instead of getting the correct child by traversing the DOM. In current code where checking fornewDomin the line you posted above and use it to compare the currentchildDomagainst it.We believe that this is necessary to fix the remaining issues with
Fragments. It's something on our todo list and that we have a few branches where we experimented with, but we're waiting for #1440 to be merged to tackle it.Besides the JSDoc comments we have a few hints in our internal typings (usually
internal.d.ts) about the use of each property.Hope this helps to get you started :)