Supporting the key-prop
This commit is contained in:
parent
51f894c616
commit
5704b72542
@ -26,17 +26,6 @@ export function getNodeMeta(vnode){
|
||||
* @property {Element} [parent] - The parent element (TODO not sure what this will do when specified; Insert it as child element of the parent where?)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Temporary data structure for listing an old VNode
|
||||
* @typedef VOldQueueItem
|
||||
* @interface
|
||||
* @category VDOM.renderer
|
||||
* @property {VNode} vnode - The old vnode
|
||||
* @property {VRenderQueueItemMetadata} meta - Meta data for the item such as normedType and the renderer to use(from a preprocessing stage)
|
||||
* @property {Element} element - The matching element
|
||||
**/
|
||||
|
||||
|
||||
/**
|
||||
* This exists as a very basic example/test for JSX-to-DOM
|
||||
* @category VDOM
|
||||
@ -103,7 +92,7 @@ export function render(vnode, opts = {}) {
|
||||
// Only items with a renderer are tracked (any other are undefined or null and shoulnd't be rendered at all)
|
||||
let childType = meta.normedType;
|
||||
if(!meta.renderer.remove) childType = 'node'; // Treat anything that doesnt have a special remove-function as ChildNode-type (e.g. it shows up in Element.childNodes)
|
||||
childTypes.add(childType);// Tract that children of this type exist and should be iterated later
|
||||
childTypes.add(childType);// Track that children of this type exist and should be iterated later
|
||||
vChildren[childType] = vChildren[childType] || []; // Make sure the array exists
|
||||
vChildren[childType].push({
|
||||
item: {
|
||||
@ -142,13 +131,17 @@ export function render(vnode, opts = {}) {
|
||||
curElement = curElement.nextSibling;
|
||||
}
|
||||
}
|
||||
childTypes.add(childType);// Tract that children of this type exist and should be iterated later
|
||||
childTypes.add(childType);// Track that children of this type exist and should be iterated later
|
||||
oldVChildren[childType] = oldVChildren[childType] || []; // Make sure the array exists
|
||||
oldVChildren[childType].push({
|
||||
let oldItem = {
|
||||
vnode: next,
|
||||
element: childElement,
|
||||
meta: meta
|
||||
});
|
||||
};
|
||||
oldVChildren[childType].push(oldItem);
|
||||
if(next.props?.key){
|
||||
state.keyedElements.set(next.key,oldItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -156,17 +149,42 @@ export function render(vnode, opts = {}) {
|
||||
|
||||
let sortedChildTypes = Array.from(childTypes).sort((a,b)=>a==='node'?1:-1); // Always do ChildNode-types last
|
||||
let queuedItems = [];
|
||||
let previous = null;
|
||||
/**@type {VRenderQueueItem}*/ let previous = null;
|
||||
for(let childType of sortedChildTypes){
|
||||
let newChildren = vChildren[childType];
|
||||
let oldChildren = oldVChildren[childType];
|
||||
|
||||
while(newChildren && newChildren.length){
|
||||
let child = newChildren.splice(0,1)[0];
|
||||
let oldChild = oldChildren && oldChildren.splice(0,1)[0];
|
||||
|
||||
|
||||
// Key handling
|
||||
let childKey = child.item.vnode.props?.key;
|
||||
/**@type {VOldQueueItem}*/ let oldChild;
|
||||
if(childKey){
|
||||
oldChild = state.keyedElements.get(childKey);
|
||||
if(oldChild) {
|
||||
if (oldChildren && oldChildren[ 0 ] === oldChild) {
|
||||
// Old keyed child already in the right place (just clear it from the queue);
|
||||
oldChildren.splice(0, 1);
|
||||
} else {
|
||||
// Old keyed child not already in the right place
|
||||
let indexOfKeyed = oldChildren.indexOf(oldChild);
|
||||
if(indexOfKeyed) {
|
||||
oldChildren.splice(indexOfKeyed, 1);
|
||||
item.host.removeChild(oldChild.element);
|
||||
}
|
||||
if (previous) {
|
||||
previous.item.host.after(oldChild.element);
|
||||
} else {
|
||||
item.parent.prepend(oldChild.element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!oldChild) oldChild = oldChildren && oldChildren.splice(0,1)[0];
|
||||
|
||||
child.previous = previous;
|
||||
if(oldChild && child.meta.normedType === oldChild.meta.normedType){
|
||||
if(oldChild && child.meta.normedType === oldChild.meta.normedType && childKey===oldChild.vnode.props?.key){
|
||||
// Update old-child
|
||||
child.item.host = oldChild.element;
|
||||
child.item.old = oldChild.vnode;
|
||||
|
||||
@ -70,7 +70,7 @@ export const NodeTreeRenderer = {
|
||||
propDiffs.push([key,newVal, undefined]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Now apply each
|
||||
for(let [key, newVal, oldVal] of propDiffs){
|
||||
if(VNODEPROP_IGNORE[key]){
|
||||
|
||||
@ -24,6 +24,15 @@ import "./vnode";
|
||||
* @property {VRenderItem} previous - The item that will have been inserted before this one
|
||||
**/
|
||||
|
||||
/**
|
||||
* Temporary data structure for listing an old VNode
|
||||
* @typedef VOldQueueItem
|
||||
* @interface
|
||||
* @category VDOM.renderer
|
||||
* @property {VNode} vnode - The old vnode
|
||||
* @property {VRenderQueueItemMetadata} meta - Meta data for the item such as normedType and the renderer to use(from a preprocessing stage)
|
||||
* @property {Element} element - The matching element
|
||||
**/
|
||||
|
||||
/**
|
||||
* Global rendering-state when rendering a tree of VNodes
|
||||
@ -32,5 +41,5 @@ import "./vnode";
|
||||
* @category VDOM.renderer
|
||||
* @property {Array.<VRenderQueueItem>} queue - The queue of items to be rendered
|
||||
* @property {Array.<[Function,Element]>} refs - Ref-callback functions be called when rendering is done
|
||||
* @property {Map.<string, VNode>} keyedElements - A map of keyed elements (TODO this needs refining)
|
||||
* @property {Map.<string, VOldQueueItem>} keyedElements - A map of (old) keyed elements
|
||||
**/
|
||||
|
||||
@ -25,6 +25,7 @@ export class MyTodo extends CustomElement{
|
||||
>
|
||||
{this.todos.map(item =>
|
||||
<todo-item
|
||||
key={item.id}
|
||||
model={ item.id }
|
||||
checked={ item.checked }
|
||||
>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user