diff --git a/src/reconciler.js b/src/reconciler.js index 9c3d8da..4b93552 100644 --- a/src/reconciler.js +++ b/src/reconciler.js @@ -10,16 +10,43 @@ export function render(element, container) { function reconcile(parentDom, instance, element) { if (instance == null) { + // Create instance const newInstance = instantiate(element); parentDom.appendChild(newInstance.dom); return newInstance; + } else if (element == null) { + // Remove instance + parentDom.removeChild(instance.dom); + return null; + } else if (instance.element.type === element.type) { + // Update instance + updateDomProperties(instance.dom, instance.element.props, element.props); + instance.childInstances = reconcileChildren(instance, element); + instance.element = element; + return instance; } else { + // Replace instance const newInstance = instantiate(element); parentDom.replaceChild(newInstance.dom, instance.dom); return newInstance; } } +function reconcileChildren(instance, element) { + const dom = instance.dom; + const childInstances = instance.childInstances; + const nextChildElements = element.props.children || []; + const newChildInstances = []; + const count = Math.max(childInstances.length, nextChildElements.length); + for (let i = 0; i < count; i++) { + const childInstance = childInstances[i]; + const childElement = nextChildElements[i]; + const newChildInstance = reconcile(dom, childInstance, childElement); + newChildInstances.push(newChildInstance); + } + return newChildInstances.filter(instance => instance != null); +} + function instantiate(element) { const { type, props } = element; diff --git a/test/03.reconciliation.test.js b/test/03.reconciliation.test.js new file mode 100644 index 0000000..f6ddb7f --- /dev/null +++ b/test/03.reconciliation.test.js @@ -0,0 +1,43 @@ +import test from "ava"; +import browserEnv from "browser-env"; +/** @jsx createElement */ +import { render, createElement } from "../src/didact"; + +// Create document global var +browserEnv(["document"]); + +test.beforeEach(t => { + let root = document.getElementById("root"); + if (!root) { + root = document.createElement("div"); + root.id = "root"; + document.body.appendChild(root); + } + t.context.root = root; +}); + +test("replace div to span", t => { + const root = t.context.root; + let element =