「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。
实现
我们将分为8步,一步一步的实现一个小型的React
- 实现createElement函数
- 实现render函数
- Currnet Mode模式
- fibers
- render和commit阶段
- 协调器
- function组件
- hooks
实现render函数
接下来我们来实现ReactDOM.render函数,继续使用笔记一的代码,新增render函数
const Didect = {
createElement,
render,
}
function render(element, container) {
// TODO create dom nodes
}
const element = (
<div id="foo">
<a>bar</a>
<b />
</div>
)
const container = document.getElementById("root")
Didect.render(element, container)
我们先根据元素的类型创建新dom节点,然后将新dom节点加入到container中,然后递归的创建子dom节点
function render(element, container) {
const dom = document.createElement(element.type);
element.props.children.forEach(child => render(child, dom))
container.appendChild(dom)
}
这里我们还需要处理text元素,如果元素的type为TEXT_ELEMENT,需要创建一个text节点
function render(element, container) {
const dom =
element.type == "TEXT_ELEMENT"
? document.createTextNode("")
: document.createElement(element.type)
element.props.children.forEach(child => render(child, dom))
container.appendChild(dom)
}
最后我们需要将属性加到dom节点上,也就是props对象里除了children的其他属性
function render(element, container) {
const dom =
element.type == "TEXT_ELEMENT"
? document.createTextNode("")
: document.createElement(element.type)
const isProperty = key => key !== "children"
Object.keys(element.props)
.filter(isProperty)
.forEach(name => {
dom[name] = element.props[name]
})
container.appendChild(dom)
}
到目前为止我们已经完成了一个简单的render函数啦,现在可以将JSX渲染为dom元素了。
总结
目前实现的render函数采用的是递归的方式创建dom节点,也是react15使用的方式。浏览器普遍的刷新率是60fps,也就是60帧每秒。也就是在16.6ms内js还没执行完,就会出现卡顿。它的主要问题是,当dom节点达到一个量级时,render递归地创建dom节点且不可中断,一直占用着线程,从而会导致页面出现卡顿的情况。
所以react会进行重构,react16实现了全新架构,主要实现了可中断异步更新。下一章我们会对render进行重构,实现可中断更新。