react jsx转换成虚拟dom到渲染页面整个过程

92 阅读2分钟

在编辑阶段 jsx标签被babel转化为React.createElement的调用,然后React.createElement函数执行后返回虚拟DOM,最后调用render方法生成真实dom

jsx语法

 <div id="compId">
    <p>text1</p>
    <p>text2</p>
 </div>

React.createElement函数参数说明 React.createElement(标签名,属性props对象, 子节点1,子节点2 …)

  1. 第一个参数必填,另两个参数选填
  2. 参数:标签名,属性对象,子节点
  3. 返回值:虚拟DOM对象

jsx标签被babel转化为React.createElement调用形式为

 React.createElement('div',{id:'compId'}, [
 React.createElement('p',null, 'text1'),
 React.createElement('p',null, 'text2')
 ])

React.createElement返回的虚拟dom数据结构如下

{
"type":"div",
"key":null,
"ref":null,
"props":{
    "id":"comp",
    "children":[
        {"type":"p","key":null,"ref":null,"props":{"children":"text1"}},
        {"type":"p","key":null,"ref":null,"props":{"children":"text2"}}
        ]
    }
}

render方法接受两个参数 render(Comp, document.getElementById('root'))

  1. 第一个参数虚拟dom

  2. 第二个参数真实dom

const render = (virtualDom,container) => {
  const {type, props} = virtualDom
  const dom = document.createElement(type) 
  Object.keys(props).filter(prop => prop !=='children').forEach(prop => {
    //将props 属性挂在dom结构上,但排除children属性
    // 注意 这是简单对属性处理,还需要对style 事件进行特色处理
    dom[prop] = props[prop]
  })
  // 如果children是数组,递归调用 render函数
  // 注意这是react.16之前版本 stack 递归渲染方式,但会存在问题,如果子阶段很多,js执行时间过长,会操作页面卡顿
  if(Array.isArray(props.children)) {
     props.children.forEach(child => render(child, dom))
  }else {
    dom.textContent = props.children
  }
  container.appendChild(dom)
}

render(Comp, document.getElementById('root'))

在jsx标签被babel转化为React.createElement的调用,生成虚拟DOM,render函数接受虚拟DOM 生成真实dom找个过程,需要关注是 数据结构的变化,render函数是对虚拟dom的树形结构进行深层遍历,生成对应dom节点

如果有数据结构的基础,特别是树形数据结构,对jsx标签到真实dom过程有比较深的理

大家对jsx标签到真实dom整个过程有什么看法,欢迎大家在评论区进行评论