SHARE
TWEET

Untitled

a guest Aug 25th, 2019 71 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { updateDomProperties } from "./dom-utils";
  2. import { TEXT_ELEMENT } from "./element";
  3.  
  4. let rootInstance = null; // will keep the reference to the instance rendered on the dom
  5.  
  6. export function render(element, parentDom) {
  7.   const prevInstance = rootInstance;
  8.   const nextInstance = reconcile(parentDom, prevInstance, element);
  9.   rootInstance = nextInstance;
  10. }
  11.  
  12. function reconcile(parentDom, instance, element) {
  13.   if (instance == null) {
  14.     // initial render
  15.     const newInstance = instantiate(element);
  16.     parentDom.appendChild(newInstance.dom);
  17.     return newInstance;
  18.   } else if (element == null) {
  19.     /**
  20.      * this section gets hit when
  21.      * a childElement was previously present
  22.      * but in the new element is not present
  23.      * for instance a todo item that has been deleted
  24.      * it was present at first but is now not present
  25.      */
  26.     parentDom.removeChild(instance.dom);
  27.     return null;
  28.   } else if (instance.element.type === element.type) {
  29.     /**
  30.      * if the types are the same
  31.      * eg: if prevType was "input" and current type is still "input"
  32.      * NB:// we still havent updated
  33.      * the props of the node rendered in the dom
  34.      */
  35.     instance.childInstances = reconcileChildren(instance, element);
  36.     instance.element = element;
  37.     return instance;
  38.   } else {
  39.     /**
  40.      * if the type of the previous Instance is not the
  41.      * same as the type of the new element
  42.      * we replace the old with the new.
  43.      * eg: if we had an "input" and now have "button"
  44.      * we get rid of the input and replace it with the button
  45.      */
  46.     const newInstance = instantiate(element);
  47.     parentDom.replaceChild(newInstance.dom, instance.dom);
  48.     return newInstance;
  49.   }
  50. }
  51.  
  52. function instantiate(element) {
  53.   const { type, props } = element;
  54.  
  55.   const isTextElement = type === TEXT_ELEMENT;
  56.   const dom = isTextElement
  57.     ? document.createTextNode("")
  58.     : document.createElement(type);
  59.  
  60.   updateDomProperties(dom, props);
  61.  
  62.   // Instantiate and append children
  63.   const childElements = props.children || [];
  64.   // we are recursively calling instanciate on each
  65.   // child element
  66.   const childInstances = childElements.map(instantiate);
  67.   const childDoms = childInstances.map(childInstance => childInstance.dom);
  68.   childDoms.forEach(childDom => dom.appendChild(childDom));
  69.  
  70.   const instance = { dom, element, childInstances };
  71.   return instance;
  72. }
  73.  
  74. function reconcileChildren(instance, element) {
  75.   const dom = instance.dom;
  76.   const childInstances = instance.childInstances;
  77.   const nextChildElements = element.props.children || [];
  78.   const newChildInstances = [];
  79.   const count = Math.max(childInstances.length, nextChildElements.length);
  80.  
  81.   for (let i = 0; i < count; i++) {
  82.     const childInstance = childInstances[i];
  83.     const childElement = nextChildElements[i];
  84.     // the reconcile function has logic setup to handle the scenario when either
  85.     // the child instance or the childElement is null
  86.     const newChildInstance = reconcile(dom, childInstance, childElement);
  87.     newChildInstances.push(newChildInstance);
  88.   }
  89.  
  90.   return newChildInstances.filter(instance => instance != null);
  91. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top