初始化一个项目

npx create-react-app my-app
cd my-app
npm start

index.js

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. let element = (
  4. <div id="A1">
  5. <div id="B1">
  6. <div id="C1"></div>
  7. <div id="C2"></div>
  8. </div>
  9. <div id="B2"></div>
  10. </div>
  11. )
  12. console.log(JSON.stringify(element, null, 2))
  13. ReactDOM.render(element, document.getElementById('root'));

经过babel转译过后的虚拟dom json对象

  1. let element = {
  2. "type": "div",
  3. "key": null,
  4. "ref": null,
  5. "props": {
  6. "id": "A1",
  7. "children": [
  8. {
  9. "type": "div",
  10. "key": null,
  11. "ref": null,
  12. "props": {
  13. "id": "B1",
  14. "children": [
  15. {
  16. "type": "div",
  17. "key": null,
  18. "ref": null,
  19. "props": {
  20. "id": "C1"
  21. },
  22. "_owner": null,
  23. "_store": {}
  24. },
  25. {
  26. "type": "div",
  27. "key": null,
  28. "ref": null,
  29. "props": {
  30. "id": "C2"
  31. },
  32. "_owner": null,
  33. "_store": {}
  34. }
  35. ]
  36. },
  37. "_owner": null,
  38. "_store": {}
  39. },
  40. {
  41. "type": "div",
  42. "key": null,
  43. "ref": null,
  44. "props": {
  45. "id": "B2"
  46. },
  47. "_owner": null,
  48. "_store": {}
  49. }
  50. ]
  51. },
  52. "_owner": null,
  53. "_store": {}
  54. }

简单实现 React 15 之前的渲染方法

  1. function render (element, parentDOM) {
  2. // 创建dom元素
  3. let dom = document.createElement(element?.type);
  4. // 处理属性
  5. Object.keys(element.props) // 返回props里的所有key
  6. .filter(key=> key!=='children') // 过滤childer 只要id
  7. .forEach(key =>{
  8. dom[key] = element.props[key]
  9. })
  10. if(Array.isArray(element?.props?.children)){
  11. // 递归调用插入子节点
  12. element.props.children.forEach(child=>render(child,dom))
  13. }
  14. parentDOM.appendChild(dom)
  15. // console.log(Object.keys(element.props).filter(key=> key!=='children'))
  16. }
  17. render(element, document.getElementById('root'));

存在的问题
1、如果节点多且层级比较深,递归无法退出
2、因为JS是单线程,UI渲染和JS执行是互斥的