初始化一个项目
npx create-react-app my-app
cd my-app
npm start
index.js
import React from 'react';
import ReactDOM from 'react-dom';
let element = (
<div id="A1">
<div id="B1">
<div id="C1"></div>
<div id="C2"></div>
</div>
<div id="B2"></div>
</div>
)
console.log(JSON.stringify(element, null, 2))
ReactDOM.render(element, document.getElementById('root'));
经过babel转译过后的虚拟dom json对象
let element = {
"type": "div",
"key": null,
"ref": null,
"props": {
"id": "A1",
"children": [
{
"type": "div",
"key": null,
"ref": null,
"props": {
"id": "B1",
"children": [
{
"type": "div",
"key": null,
"ref": null,
"props": {
"id": "C1"
},
"_owner": null,
"_store": {}
},
{
"type": "div",
"key": null,
"ref": null,
"props": {
"id": "C2"
},
"_owner": null,
"_store": {}
}
]
},
"_owner": null,
"_store": {}
},
{
"type": "div",
"key": null,
"ref": null,
"props": {
"id": "B2"
},
"_owner": null,
"_store": {}
}
]
},
"_owner": null,
"_store": {}
}
简单实现 React 15 之前的渲染方法
function render (element, parentDOM) {
// 创建dom元素
let dom = document.createElement(element?.type);
// 处理属性
Object.keys(element.props) // 返回props里的所有key值
.filter(key=> key!=='children') // 过滤childer 只要id
.forEach(key =>{
dom[key] = element.props[key]
})
if(Array.isArray(element?.props?.children)){
// 递归调用插入子节点
element.props.children.forEach(child=>render(child,dom))
}
parentDOM.appendChild(dom)
// console.log(Object.keys(element.props).filter(key=> key!=='children'))
}
render(element, document.getElementById('root'));
存在的问题
1、如果节点多且层级比较深,递归无法退出
2、因为JS是单线程,UI渲染和JS执行是互斥的