【组件本质学习】

import React, {Component, useState, useEffect,} from 'react';

class MyComponent {
  render() {
    return {
      tag: 'div'
    }
  }
}

// 函数式组件:
//
// 是一个纯函数
// 没有自身状态,只接收外部数据
// 产出 VNode 的方式:单纯的函数调用
// 有状态组件:
//
// 是一个类,可实例化
// 可以有自身状态
// 产出 VNode 的方式:需要实例化,然后调用其 render 函数

export default () => {
  // // init方法用来创建patch函数
  // const patch = init([])
  // // 我所创建的组件, 组件的作用就是返回一个虚拟dom
  // /****
  //  *
  //  * @param props
  //  * @constructor
  //  * Virtual DOM带来了分层设计,它对渲染过程的抽象,使得框架可以渲染到web(浏览器)
  //  * 以外的平台,以及能够实现SSR(Server Side Rendering)
  //  */
  // const MyComponent = (props: any) => {
  //   return h('h1', props.title)
  // }
  // // 组件返回的是虚拟DOM
  // const prevVnode = MyComponent({title: 'aaa'});
  // // 调用patch函数渲染为真实DOM
  // patch(document.body, prevVnode);
  //
  // // 数据变化,返回新的VNode
  // const nextVnode = MyComponent({title: 'sunwukong1'});
  // // 通过对比新旧Vnode, 高效的渲染真实DOM
  // patch(prevVnode, nextVnode)
  // console.log('aaaaa', patch(document.body, prevVnode));

  //---------------------------------------------
  //Vnode 用如下对象表示一个div标签
  const elementVnode = {
    tag: 'div'
  };

  // 表示一个虚拟组件Vnode
  const componentVnode = {
    tag: MyComponent
  };

  // 把Vnode 渲染为真实DOM
  function render(vnode: any, container: any) {
    // 根据vnode创建真实DOM并添加到容器中
    if (typeof vnode.tag === 'string') {// html标签
      mountElement(vnode, container);
    } else { // 组件
      mountComponent(vnode, container);
    }
  }

  // 创建真实dom并添加到容器中
  function mountElement(vnode: any, container: any) {
    // 创建元素
    const element = document.createElement(vnode.tag);
    // 将元素添加到容器
    container.appendChild(element);
  }

  // 创建组件
  function mountComponent(vnode: any, container: any) {
    console.log('componentVnode', componentVnode, new componentVnode.tag())
    //  创建组件实例
    const instance = new vnode.tag();
    //  渲染
    instance.$vnode = instance.render();
    //  挂载
    mountElement(instance.$vnode, container)
  }


  useEffect(() => {
    // 调用render函数
    render(elementVnode, document.getElementById('app'));
    render(componentVnode, document.getElementById('app'))
  }, []);

  return (
    <div id={'app'} className={"div"}>
      divdivdiv

    </div>
  )
}