聊聊React源码系列 - 虚拟DOM
--- JSX 是什么 ---
我们在React项目中直接使用的开发代码就是JSX,例如
我们在浏览器中将main输出看一下返回的是什么
这个输出的函数 React.createElement就是经过一次babel处理的
--- Babel ---
我们直接在Babel官网中看看一段普通的JSX会被编译成什么
而执行此函数会返回什么呢
--- VitrualDom ---
这个对象就是今天我们要说的重点,虚拟Dom
返回的DOM对象抽取一些重要的属性
{
$$typeof: Symbol(react.element)
key: null
ref: null
props: { childern: xxx }
ref: null
type: xxx
}
这个对象就是虚拟dom
简单总结上述流程
明白了这个DOM生成阶段,我们来重点看看 VitrualDom
自己尝试实现这个生成虚拟DOM的函数
先写只有一个子元素的对象
function createElement(type, config, ...childrens) {
let { ref = null, key = null, ...propsConfig } = config || {}
const obj = {
$$typeof: Symbol.for('react.element'),
type,
ref,
key,
props: { ...propsConfig },
}
// 处理children
obj.props.children = childrens.length > 1 ? childrens : childrens[0]
return obj
}
基本的功能完成 👍
虚拟DOM对象转为页面中真实的DOM树,是通过React.render函数,也来写一个render函数
function createReallyDom(virtualDom, root) {
const { type, props } = virtualDom
const dom = document.createElement(type)
// 遍历处理props
const { children = [], ...restProps } = props || {}
// 处理子元素
if (Array.isArray(children) && children.length) {
createChildrens(children, root)
} else {
dom.innerText = children
}
for (const key in restProps) {
dom[key] = restProps[key]
}
// 真实DOM 写入父节点
root.appendChild(dom)
}
function createChildrens(children, root) {
if (Array.isArray(children)) {
children.forEach((child) => {
createReallyDom(child, root)
})
} else {
createReallyDom(children, root)
}
}
function render(virtualDom, root) {
createReallyDom(virtualDom, root)
}
一个极简版本的render完成 👍
总结:
虚拟DOM是一个React创建的对象,在浏览器中通过render方法可以渲染出真实DOM节点