image.png

在babel中, 勾上React, 输入如下代码:

let div = <div id="test">test <span> test</span><p>nihao</p></div>

然后右边就会输出:

"use strict";

var div = React.createElement(
  "div",
  { id: "test" },
  "test ",
  React.createElement(
    "span",
    null,
    " test"
  ),
  React.createElement(
    "p",
    null,
    "nihao"
  )
);

那么react在遇到这样的代码之后, 是会去找React下的createElement函数.
react中, 编写的jsx代码, 就是React.createElement的语法糖. 方便编写.
jsx => React.createElement => vNode => render 这就是react 的渲染流程.

react 环境下, 如果直接写入jsx, 肯定是会被转换为上述格式的js代码的.如果我们打印一下这个div:

image.png

那么主要的属性也就是: ref, type, props, key 那就可以简易的模拟一下:
const React = {
    createElement(type, props, ...children){
        return {
            type,
            props,
            children
        }
    }
}

然后将divjsx打印(react环境会自己去找React.createElement方法)

image.png

执行完毕就会扔出来这么个对象 => Vnode
虚拟dom都已经有了, render想来也不是什么难事

// react 的render
ReactDOM.render('<App />', document.getElementById('root'))

MyRender(vNode, container){
    if(typeof vnode === 'string'){ // 文本直接添加进去
        const text = document.createTextNode(vnode)
        container.appendChild(text)
        return
    }
    const {type, props, children } = vnode
    const el = document.createElement(type)
    for (let key in props){
        // 将原有的属性添加上去
        // 过滤掉原型上的属性
        if(key.startsWith("__")){
            continue
        }
        el.setAttribute(key, props[key])
    }
    children.forEach(item=>{
        // 递归子元素
        render(item, el)
    })
    container.appendChild(el)
}

MyRender(div, window.root) // document.getElementById('root')
image.png

image.png