React原理(一):动手实现React.createElement和ReactDOM.render

首先我们来看一个最简单的hello world例子

function App() {
  return (
      

hello world

); } ReactDOM.render(, document.getElementById("root"));

在babel中转化为如下代码

function App() {
  return React.createElement(
    "p",
    { className: "title" },
    "hello world"
  );
}

ReactDOM.render(React.createElement(APP, null), document.getElementById("root"));

打印App(),返回的对象就是一个虚拟DOM

React原理(一):动手实现React.createElement和ReactDOM.render_第1张图片
屏幕快照 2018-11-28 00.34.27.png

实现React.createElement

通过上文,我们可以知道jsx本质是个语法糖。jsx片段会被转译成用React.createElement方法包裹的代码。所以第一步,我们来实现这个React.createElement方法

function createElement(tag, attrs, ...children){
    return {
        tag,
        attrs,
        children
    }
}

第一个参数是DOM节点的标签名

第二个参数是一个对象,里面保存了所有的属性

从第三个参数开始,就是它的子节点。

我们的createElement方法返回的对象记录了这个DOM节点所有的信息,换言之,通过它我们就可以生成真正的DOM,这个记录信息的对象我们称之为虚拟DOM

实现ReactDOM.render

我们来看这段代码

ReactDOM.render(
  React.createElement("p", { className: "title" }, "hello world"),
  document.getElementById("root")
)

所以render的第一个参数实际上接受的是createElement返回的对象,也就是虚拟DOM
而第二个参数则是挂载的目标DOM

我们来实现这个render方法

  function render(vnode, container) {
    //当vnode为字符串时,渲染结果是一段文本
    if (typeof vnode === "string") {
      const textNode = document.createTextNode(vnode)
      return container.appendChild(textNode)
    }

    const dom = document.createElement(vnode.tag)

    //设置属性
    if (vnode.attrs) {
      Object.keys(vnode.attrs).forEach(key => {
        const value = vnode.attrs[key]
        dom.setAttribute(key, value)
      })
    }

    //递归渲染子节点
    vnode.children.forEach(child=> render(child, dom))

    return container.appendChild(dom)
  }

参考资料

从零开始实现一个React(一):JSX和虚拟DOM

你可能感兴趣的:(React原理(一):动手实现React.createElement和ReactDOM.render)