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>
)
相关推荐
铁皮饭盒17 分钟前
用 Bun.cron 定时 7 月 7 日,为啥? 看图1
javascript
大圣编程1 小时前
Python中continue语句的用法是什么?
开发语言·前端·python
yuhaiqiang1 小时前
随手 vibecoding 的浏览器插件已经 6000 多次下载,聊聊他的产品设计
前端·后端·面试
之歆2 小时前
Vue商品详情与放大镜组件
前端·javascript·vue.js
再吃一根胡萝卜3 小时前
如何把小米 MiMo 接入 CodeBuddy,打造私有 Agent
前端
负责的蛋挞4 小时前
异步HttpModule的实现方式
java·服务器·前端
YFF菲菲兔5 小时前
其他 Hooks 解析
react.js
丹宇码农6 小时前
把 HLS 字幕玩出花:zwPlayer 如何让 M3U8 视频支持全文搜索、翻译与码率自适应
前端·javascript·音视频·hls·视频播放器
2501_943782357 小时前
【共创季稿事节】猜数字游戏:二分法思维与交互式反馈
前端·游戏·microsoft·harmonyos·鸿蒙·鸿蒙系统