本节目标实现ReactDOM.render,只关心向 DOM 添加内容,之后处理更新和删除内容;

本节代码实现目录为:react/react-dom.js文件;

有了虚拟 DOM 数据结构,接下来要把它转换成真实的DOM结构渲染到页面上,基本分为四步:

  • 创建不同类型节点
  • 添加属性 props
  • 遍历 children,递归调用 render
  • 将生成的节点 append 到 root 根节点上

具体实现步骤:

1、新建react-dom.js文件

image.png

2、创建 DOM 节点,然后将新节点添加到容器

  1. // react/react-dom.js
  2. /**
  3. * 将虚拟 DOM 转换为真实 DOM 并添加到容器中
  4. * @param {element} 虚拟 DOM
  5. * @param {container} 真实 DOM
  6. */
  7. function render(element, container) {
  8. const dom = document.createElement(element.type)
  9. container.appendChild(dom)
  10. }

3、将 element.props.children 都添加至 dom 节点中

  1. element.props.children.forEach(child =>
  2. render(child, dom)
  3. )

4、处理文本节点

  1. const dom =
  2. element.type == "TEXT_ELEMENT"
  3. ? document.createTextNode("")
  4. : document.createElement(element.type)

5、为节点绑定属性

  1. // 为节点绑定属性
  2. const isProperty = key => key !== "children"
  3. Object.keys(element.props)
  4. .filter(isProperty)
  5. .forEach(name => {
  6. dom[name] = element.props[name]
  7. })

6、测试

以上我们实现了一个jsx转换为dom的库,测试一下:

6.1 将render方法引入到react/index.js文件中

image.png

6.2 添加React.render方法

在src/index.js文件添加React.render方法:

  1. // src/index
  2. import React from '../react';
  3. const element = (
  4. <div id="foo">
  5. <a>bar</a>
  6. <b />
  7. </div>
  8. )
  9. React.render(element, document.getElementById('root'))

6.3 修改webpack配置

在src目录下添加index.html文件,并添加一个dom属性为id的节点:
image.png

修改webpack配置,添加html模板:
image.png
image.png

6.4 运行

运行命令 npm run start 启动,可以看到已经成功显示出结果:
image.png

7、总结

使用流程图简单总结一下2、3小节:
image.png

8、本节代码

代码地址:https://github.com/linhexs/mini-react/tree/2.render