JSX底层渲染机制【react】

JSX底层渲染机制:

  1. 将编写的jsx语法编译为虚拟dom对象;
  2. 将构建的虚拟dom对象渲染为真实dom;
  3. 将真实dom渲染到页面中,第一次渲染页面是直接从虚拟dom转化编译为真实dom,后期更新视图时,需要经过dom-diff算法的对比计算出补丁包patch(两次差异部分),将patch补丁包渲染到页面中。

函数组件渲染机制:

  1. 基于babel-preset-react-app将调用的组件转化换为React.createElement()格式。
  2. 执行React.createElement()创建虚拟dom。
  3. 基于render方法将虚拟dom变为真实dom,把虚拟dom中props作为实参传递给函数,接收函数执行的返回结果,当前组件的虚拟dom基于render吧组件返回的xunidom变为真实dom,插入到root容器中。
  4. 调用组件时,可以调用组件设置各种各样的属性,如果设置的属性值不是字符串格式,需要基于{}设置,调用组件时可以将一些数据通过props传递给组件,双闭合调用可以传递给子节点,在传递给函数的props中有children属性用于存储子节点。

JSX底层原理

typescript 复制代码
// 1. 基于babel-preset-react-app语法包将jsx语法编译为React.createElement()格式
// 2. 执行createElement方法,创建虚拟dom
// 在react中<></> 为React.Fragement 空文本标记标签
// 传参格式:(ele,props,...children)
// ele:元素标签,组件名
// props:元素属性集合,如果不设置为null,
// children:第三个及以后的元素为当前元素的子节点
React.createElement(
   React.Fragement,
   null,
   React.createElement('h2',{className:'title'},'\u73E0'),
   React.createElement(
      'div',
      {className:'box'}, 
      React.createElement('span',null,x),
   ),
)

// 使用jsx文件处理生成dom对象,createElement原理
function createElement(ele,props,...children){
     const virtualDOM = {
         $$typeof:Symbol('react.element'),
         key:null,
         ref:null,
         type:null,
         props:{}
     }
     // 定义传进来的children长度为length
     let length = children.length
     // 将ele赋值给virtualDOM.type
     virtualDOM.type = ele
     // 判断props是否为null
     if(props!==null){
        virtualDOM.props = [...props]
        if(length === 1){
           virtualDOM.props.children = children[0]
        }
        if(length > 1){
           virtualDOM.props.children = children
        }
     }
     return virtualDOM
}

// 封装基于迭代的对象方法
const each = function each(obj,callback){
   if(obj ===null || typeof obj !=='object'){
      throw new TypeError('obj is not object')
   }
   if(typeof callback !== 'function'){
      throw new TypeError('callback is not function')
   }
   // Reflect.ownkeys(obj)返回一个由目标对象自身的可枚举属性键(不包括原型链上的属性)组成的数组。
   let keys = Reflect.ownkeys(obj)
   keys.forEach((i)={
      let val = obj[i]
      // 每次迭代调用回调函数并执行
      callback(val,i)
   })
}

// 虚拟dom变为真实dom
function render(virtualDOM){
    let { type, props } = virtualDOM
    if(typeof type==='string'){
        // 存储的是标签名,动态创建标签
        let ele = document.createElement(type)
        // 遍历props,为标签设置相关属性/子节点,
        each(props, (value,key)=>{
            // className处理,定义类名
            if(key==='className'){
                ele.className = value
                return;
            }
            // style处理,样式对象
            if(key==='style'){
               each(value,(value,attr)=>{
                   ele.style[attr] = value
               })
               return;
            }
            if(key==='children'){
               // 判断是否为数组,如果不是数组时为字符串
               if(!Array.isArray(children)) children = [value]
               value.forEach((child)=>{
                  if(typeof child==='string'){
                      ele.appendChild(document.createTextNode(child))
                      return;
                  }
                  // 子节点是v-dom,递归处理
                  render(child,ele)
               })
               return;
            }
            ele.setAttribute(key,value)
        })
        // 将新增的标签添加到指定容器中,this指向root容器
        this.appendChild(ele)
    }
}

// v16版本
ReactDOM.render(
   <div className='container'>
       <h1>哈哈哈哈哈</h1>
    </div>,
    document.getElementById('root')
)

// v18版本
import { createRoot } from 'react-dom/client'
const container = document.getElementById('root') as HTMLElement
const root = createRoot(container)
root.render(
    <div className='container'>
       <h1>哈哈哈哈哈</h1>
    </div>
)
相关推荐
酒尘&4 小时前
JS数组不止Array!索引集合类全面解析
开发语言·前端·javascript·学习·js
学历真的很重要4 小时前
VsCode+Roo Code+Gemini 2.5 Pro+Gemini Balance AI辅助编程环境搭建(理论上通过多个Api Key负载均衡达到无限免费Gemini 2.5 Pro)
前端·人工智能·vscode·后端·语言模型·负载均衡·ai编程
用户47949283569155 小时前
"讲讲原型链" —— 面试官最爱问的 JavaScript 基础
前端·javascript·面试
用户47949283569155 小时前
2025 年 TC39 都在忙什么?Import Bytes、Iterator Chunking 来了
前端·javascript·面试
2401_860319525 小时前
在React Native鸿蒙跨平台开发中实现 二叉搜索树,如何实现一些基本的遍历方法,如中序遍历,中序遍历按顺序访问左子树、根节点、右子树
react native·react.js·harmonyos
大怪v6 小时前
【Virtual World 04】我们的目标,无限宇宙!!
前端·javascript·代码规范
狂炫冰美式6 小时前
不谈技术,搞点文化 🧀 —— 从复活一句明代残诗破局产品迭代
前端·人工智能·后端
xw57 小时前
npm几个实用命令
前端·npm
!win !7 小时前
npm几个实用命令
前端·npm
代码狂想家7 小时前
使用openEuler从零构建用户管理系统Web应用平台
前端