vlambda博客
学习文章列表

聊聊React源码系列 - 虚拟DOM


 --- JSX 是什么 --- 


我们在React项目中直接使用的开发代码就是JSX,例如


聊聊React源码系列 - 虚拟DOM



我们在浏览器中将main输出看一下返回的是什么


聊聊React源码系列 - 虚拟DOM


这个输出的函数 React.createElement就是经过一次babel处理的


 --- Babel ---    


我们直接在Babel官网中看看一段普通的JSX会被编译成什么


聊聊React源码系列 - 虚拟DOM



而执行此函数会返回什么呢


聊聊React源码系列 - 虚拟DOM


--- VitrualDom ---

 

这个对象就是今天我们要说的重点,虚拟Dom


返回的DOM对象抽取一些重要的属性

{ $$typeof: Symbol(react.element) key: null ref: null  props: { childern: xxx } ref: null  type: xxx}


这个对象就是虚拟dom


简单总结上述流程


聊聊React源码系列 - 虚拟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节点