The working code at the end of chapter Component class

    1. index.js
    2. function createVComponent(tag, props) {
    3. return {
    4. tag: tag,
    5. props: props,
    6. dom: null,
    7. }
    8. }
    9. function createVElement(tag, config, children = null) {
    10. const { className, style } = config;
    11. return {
    12. tag: tag,
    13. style: style,
    14. props: {
    15. children: children,
    16. },
    17. className: className,
    18. dom: null,
    19. }
    20. }
    21. function createElement(tag, config, children) {
    22. // If the tag is a function. We have a component!
    23. // we will see later why.
    24. if (typeof tag === 'function') {
    25. //of course we could do some checks here if the props are
    26. //valid or not.
    27. const vNode = createVComponent(tag, config);
    28. return vNode;
    29. }
    30. //Add children on our props object, just as in React. Where
    31. //we can acces it using this.props.children;
    32. const vNode = createVElement(tag, config, children);
    33. return vNode;
    34. }
    35. function mount(input, parentDOMNode) {
    36. if (typeof input === 'string' || typeof input === 'number') {
    37. //we have a vText
    38. return mountVText(input, parentDOMNode);
    39. }
    40. else if (typeof input.tag === 'function') {
    41. //we have a component
    42. return mountVComponent(input, parentDOMNode);
    43. }
    44. // for brevity make an else if statement. An
    45. // else would suffice.
    46. else if (typeof input.tag === 'string') {
    47. //we have a vElement
    48. return mountVElement(input, parentDOMNode)
    49. }
    50. }
    51. function mountVComponent(vComponent, parentDOMNode) {
    52. const { tag, props } = vComponent;
    53. // build a component instance. This uses the
    54. // defined Component class. For brevity
    55. // call it Component. Not needed ofcourse, new tag(props)
    56. // would do the same.
    57. const Component = tag;
    58. const instance = new Component(props);
    59. // The instance or Component has a render() function
    60. // that returns the user-defined vNode.
    61. const nextElement = instance.render();
    62. // the nextElement can be a vElement or a
    63. // vComponent. mountVComponent doenst't care. Let the mount()
    64. // handle that!
    65. const dom = mount(nextElement, parentDOMNode);
    66. //append the DOM we've created.
    67. parentDOMNode.appendChild(dom);
    68. return dom;
    69. }
    70. function mountVText(vText, parentDOMNode) {
    71. // Oeeh we received a vText with it's associated parentDOMNode.
    72. // we can set it's textContent to the vText value.
    73. // https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent
    74. parentDOMNode.textContent = vText;
    75. }
    76. function mountVElement(vElement, parentDOMNode) {
    77. const { className, tag, props, style } = vElement;
    78. const domNode = document.createElement(tag);
    79. vElement.dom = domNode;
    80. if (props.children) {
    81. // Oeh, we have children. Pass it back to our mount
    82. // function and let it determine what type it is.
    83. props.children.forEach(child => mount(child, domNode));
    84. }
    85. if (className !== undefined) {
    86. domNode.className = className;
    87. }
    88. if (style !== undefined) {
    89. Object.keys(style).forEach(sKey => domNode.style[sKey] = style[sKey]);
    90. }
    91. parentDOMNode.appendChild(domNode);
    92. return domNode;
    93. }
    94. class Component {
    95. constructor(props) {
    96. this.props = props || {};
    97. }
    98. setState(partialNewState) {
    99. // Awesome things to come
    100. }
    101. //will be overridden
    102. render() {}
    103. }
    104. //get native DOM, For now let's use the body;
    105. const root = document.body;
    106. //create vElement
    107. class App extends Component {
    108. render() {
    109. return createElement('div', { style: { height: '100px', background: 'red'} }, [
    110. createElement('h1', {}, [ this.props.message ])
    111. ]);
    112. }
    113. }
    114. mount(createElement(App, { message: 'Hello there!' }), root);