Advertisement
Guest User

Untitled

a guest
Aug 25th, 2019
145
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.06 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement