说说React render方法的作用原理?

最近使用react的比较多,记录一下一些react的面试题及自己的一些理解和补充,整理成文章更有助于梳理每个知识点的脉络。

Render的形式

在React中,render函数有两种形式:

  1. Class 组件 : 在类组件中,render方法是必需的。这个方法返回一个React元素,描述了组件在特定时间点应该渲染出的内容。例如:

    js 复制代码
    import React, { Component } from 'react';
    
    class MyComponent extends Component {
      render() {
        return <div>Hello, World!</div>;
      }
    }
  2. 函数组件 : 在函数组件中,render函数是函数本身。它接受props作为参数,并返回一个React元素。这个函数被调用时,会根据传入的props和组件内部的逻辑来决定要渲染的内容。例如:

    js 复制代码
    import React from 'react';
    
    function MyComponent(props) {
      return <div>Hello, {props.name}!</div>;
    }

render的原理

创建React元素树

在React应用中,开发者使用JSX语法编写组件的UI结构。当调用render方法时,React会将JSX转换为虚拟DOM(Virtual DOM)元素树

Render主要是把我们编写的jsx通过babel编译后就会转化成我们熟悉的js格式,比如下面这个代码:

javascript 复制代码
return (
  <div className='uname'>
    <Header> hello </Header>
    <div> world </div>
    Hello World
  </div>
)

babel编译后:

kotlin 复制代码
return (
  React.createElement(
    'div',
    {
      className : 'uname'
    },
    React.createElement(
      Header,
      null,
      'hello'
    ),
    React.createElement(
      'div',
      null,
      'world'
    ),
    'hello world'
  )
)

babel对render中的节点转换为虚拟节点,这些虚拟DOM树最终会渲染成真实DOM

比较虚拟DOM

在进行初次渲染或更新时,React会比较前后两次渲染的虚拟DOM树的差异。。React使用一种高效的算法来比较两棵虚拟DOM树的差异,并找出需要更新的部分。一般采用的是diff算法

生成DOM更新操作

js 复制代码
return (
  React.createElement(
    'div',
    {
      className : 'uname'
    },
    React.createElement(
      Header,
      null,
      'hello'
    ),
    React.createElement(
      'div',
      null,
      'world'
    ),
    'hello world'
  )
)

例如,如果新的虚拟DOM树与旧的虚拟DOM树有差异,React可能会生成一些DOM更新操作,如添加、移除或更新DOM元素,而这些操作都是应用在虚拟树上。通过虚拟树上的createElement来创建真实的元素。

应用DOM更新

React会将生成的DOM树更新操作应用到实际的DOM上,以反映最新的UI状态。

例如,如果需要添加新的DOM元素,React会将其添加到DOM树中;如果需要更新现有的DOM元素,则会更新对应的DOM属性和内容;如果需要移除DOM元素,则会将其从DOM树中移除。

React并不会每次调用render方法都直接操作实际的DOM。而是对虚拟树并进行比较和处理,然后再将最终的更新操作应用到实际的DOM上。这种通过虚拟DOM来管理和更新UI的方式,能够提高性能并减少不必要的DOM操作,从而改善用户体验。

总结

render将JSX编写的UI元素转换为虚拟dom树,最终会称为真实的节点,并且虚拟dom树可以通过diff算法来比较虚拟dom,高效的查找到需要更新的元素,通过操作虚拟树而非真实节点的方式来进行新增、更新、移除等操作。

如果觉得有趣或有收获,请关注我的更新,给个喜欢和分享。您的支持是我写作的最大动力!

往期好文推荐

相关推荐
子兮曰10 小时前
TypeScript 7.0 RC 深度解读:Go 重写完成,10 倍提速,编译器的「奇点时刻」
前端·后端·typescript
还有多久拿退休金10 小时前
让飞书知识库跟着 commit 自己长:一套自动化知识库的真实实现
前端·算法·架构
kosan10 小时前
.NET/C# 实战:我如何把登录验证码从“裸奔”改到“铜墙铁壁”
后端
王中阳Go11 小时前
AI编程实践:规则 + 技能 + 子代理 + 钩子,拆解Trae AI 开发规范的完整落地范式
后端·agent·ai编程
喝拿铁写前端11 小时前
AI 时代,ESLint 应该怎么做得更好
前端·人工智能·代码规范
YIAN11 小时前
LangChain JS 工具调用实战:基于 DeepSeek-V4-Flash 实现本地文件读取 AI 代码助手(完整可运行源码)
javascript·langchain·前端框架
码事漫谈11 小时前
放下代码洁癖,享受挖坑人生
后端
_张有志_11 小时前
手撕 STL:一棵红黑树,凭什么同时撑起 set 和 map?
后端
妙码生花11 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(二十七):管理员登录验证码开关
前端·后端·ai编程
尼斯湖皮皮怪11 小时前
iceCoder 记忆系统深度分析
前端·javascript