react渲染过程

news/2024/7/15 17:30:58 标签: react.js, javascript, 前端

一、渲染过程

渲染:生成用于显示的对象,以及将这些对象形成真实的DOM对象。
React元素:React Element,通过React.createElement创建(语法糖:JSX)
例如:

javascript"> <div>测试数据</div>

React节点:专门用于渲染到UI界面的对象,React会通过React元素,创建React节点,注意ReactDOM一定是通过React节点来进行渲染的(而不是React元素)。在这里插入图片描述
节点类型有哪些?

  • React DOM节点(不是真实的dom):创建该节点的React元素类型是一个字符串
javascript">import React from 'react';
import ReactDOM from 'react-dom';
const app = <div><h1>标题</h1></div>
ReactDOM.render(app, document.getElementById('root'));

在这里插入图片描述

  • React 组件节点:创建该节点的React元素类型是一个函数或是一个
javascript">import React from 'react';
import ReactDOM from 'react-dom';
import App from "./App"
ReactDOM.render(<App />, document.getElementById('root'));

在这里插入图片描述

  • React 文本节点:由字符串、数字创建的
javascript">import React from 'react';
import ReactDOM from 'react-dom';
const app = 'Hello World'
ReactDOM.render(app, document.getElementById('root'));

在这里插入图片描述

  • React 空节点:由null、undefined、false、true
javascript">import React from 'react';
import ReactDOM from 'react-dom';
const app = null
ReactDOM.render(app, document.getElementById('root'));

  • React 数组节点:该节点由一个数组创建
javascript">import React from 'react';
import ReactDOM from 'react-dom';
const app = [1,2,3,4]
ReactDOM.render(app, document.getElementById('root'));

注意app 这里不能直接写一个对象,普通对象是无法渲染的。

再补充下什么是真实dom?

真实DOM:通过document.createElement创建的dom元素

二、首次渲染(新节点渲染)

这里总结的是第一次渲染时:

A. 通过参数的值创建节点(参数是以上的几种类型,注意一定不能是对象)。
B. 根据不同的节点,做不同的事情。

  1. 文本节点:通过document.createTextNode创建真实的文本节点;

  2. 空节点:什么都不做

  3. 数组节点:遍历数组,将数组每一项递归创建节点(回到第A步进行反复操作,直到遍历结束)

  4. DOM节点:通过document.createElement创建真实的DOM对象,然后立即设置该真实DOM元素的各种属性,然后遍历对应React元素的children属性,递归操作(回到第A步进行反复操作,直到遍历结束)

  5. 组件节点

    1、函数组件
    调用函数(该函数必须返回一个可以生成节点的内容,若返回一个对象就不行,以为对象不能生成节点),将该函数的返回结果递归生成节点(回到第A步进行反复操作,直到遍历结束)
    2、类组件
    1.创建该类的实例
    2.立即调用对象的生命周期方法:static getDerivedStateFromProps
    3.运行该对象的render方法,拿到节点对象(将该节点递归操作,回到第A步进行反复操作)
    4.将该组件的componentDidMount加入到执行队列(先进先出,先进先执行),当整个虚拟DOM树全部构建完毕并且将真实的DOM对象加入到容器中后执行该队列(先进先执行,子组件的先执行,父组件的后执行)
    注:这个过程是很靠后的,等D执行完后才执行的,

C. 生成出虚拟DOM树之后,将该树(对象)保存起来,以便后续使用

D. 将之前生成的真实的DOM对象(下图中的黄色的部分),加入到容器中。

例子如下:
例1:DOM节点

javascript">import React from 'react';
import ReactDOM from 'react-dom';
const app = <div className="assaf">
    <h1>
        标题
        {["abc", null, <p>段落</p>]}
    </h1>
    <p>
        {undefined}
    </p>
</div>;
ReactDOM.render(app, document.getElementById('root'));

在这里插入图片描述
形成的这个图就是虚拟dom树,我们发现有些节点是不会生成真实dom的。
在这里插入图片描述
例2:函数组件:

javascript">App.js
import React from 'react'

function Comp1(props) {
  return <h1>Comp1 {props.n}</h1>
}

export default function App(props) {
  return (
      <div>
          <Comp1 n={5} />
      </div>
  )
}

javascript">import React from 'react';
import ReactDOM from 'react-dom';
import App from "./App"

const app = <App />;
ReactDOM.render(app, document.getElementById('root'));

遵循上述过程,先调用组件App,返回DOM节点div,div内部又是个组件节点,又调用Comp1函数…最终生成虚拟DOM树
在这里插入图片描述

javascript">import React from 'react'


class Comp1 extends React.Component {
  state = {}
  constructor(props){
    super(props);
    console.log(4,"Comp1 constructor")
  }
  static getDerivedStateFromProps(props,state){
    console.log(5,"Comp1 getDerivedStateFromProps")
    return null
  }
  componentDidMount(){
    console.log('b componentDidMount')
  }
  render() {
    console.log(6,"Comp1 render")
      return (
          <h1>Comp1</h1>
      )
  }
}

export default class App extends React.Component {
  state = {}
  constructor(props){
    super(props);
    console.log(1,"App constructor")
  }
  static getDerivedStateFromProps(props,state){
    console.log(2,"App getDerivedStateFromProps")
    return null
  }
  componentDidMount(){
    console.log('a componentDidMount')
  }
  render() {
    console.log(3,"App render")
      return (
          <div>
              <Comp1 />
          </div>
      )
  }
}

在这里插入图片描述

通过运行我们发现了输出的结果,其实类组件的渲染过程和函数组件是类似的。由于是等Comp1组件挂载完成,App组件才算挂载完成,所以b比a先输出。


http://www.niftyadmin.cn/n/5308745.html

相关文章

Django Auth登录实战

前言 目标&#xff1a;实现用户登录和注销功能。涉及django登录知识点&#xff0c;如登录的用户名密码如何验证&#xff0c;输出错误如何提示&#xff0c;当用户未登陆时访问功能页面如何让用户去登录&#xff08;DjangoAuth&#xff0c;类似过滤器&#xff09;等。 效果图 开…

关于“Python”的核心知识点整理大全65

目录 20.2.19 设置 SECRET_KEY 20.2.20 将项目从 Heroku 删除 注意 20.3 小结 附录 A 安装Python A.1.1 确定已安装的版本 A.1.2 在 Linux 系统中安装 Python 3 A.2 在 OS X 系统中安装 Python A.2.1 确定已安装的版本 A.2.2 使用 Homebrew 来安装 Python 3 注意 …

读元宇宙改变一切笔记01_起源

1. 元宇宙是我们下一个生存之地 1.1. 1968年&#xff0c;只有不到10%的美国家庭拥有彩色电视&#xff0c;但当年票房排名第二位的电影《2001&#xff1a;太空漫游》&#xff08;2001: A Space Odyssey&#xff09;设想了这样的未来 1.1.1. 斯坦利库布里克(Stanley Kubrick) …

c# OpenCvSharp透视矫正参数调整器

透视矫正不够智能化&#xff0c;每次都要进行局部参数调整&#xff0c;不便于程序使用&#xff0c;程序流程还是那几个步骤&#xff1b; 1、读取图像、灰度化 2、高斯滤波 3、二值化 4、边缘检测 灰度化图 上个图看看经过调整透视矫正边缘检测结果我还是挺满意的 发现一个…

贯穿设计模式-享元模式思考

写享元模式的时候&#xff0c;会想使用ConcurrentHashMap来保证并发&#xff0c;没有使用双重锁会不会有问题&#xff1f;但是在synchronize代码块里面需要尽量避免throw异常&#xff0c;希望有经验的同学能够给出解答&#xff1f; 1月6号补充&#xff1a;没有使用双重锁会有问…

【Python】Excel不同sheet另存为不同CSV

我有一个excel&#xff0c;内有不同sheet&#xff0c;现在批量生成不通csv文件&#xff0c;并以sheet名命名&#xff0c;或根据sheet名调整命名。 # 读取新的Excel文件 df pd.read_excel(rD:\itm\data.xlsx, sheet_nameNone)# 遍历每个sheet&#xff0c;将其另存为不同的CSV文…

在数据库造数据发现的bug也是bug

上个月&#xff0c;我和开发小哥讨论过一个问题&#xff0c;开发小哥专门提醒我&#xff0c;页面上新增功能尽可能在前端造一些数据去测试&#xff0c;如果直接从数据库里插入的数据&#xff0c;定位问题还是有些说不清楚。 讨论的过程和细节就是以下的对话内容&#xff1a; …

2022年多元统计分析期中试卷

多元正态均值检验 一、去年卖出的一岁牛犊的平均身高为 51 英寸&#xff0c;平均背脂厚度是 0.3 英寸&#xff0c;平均肩高是 56 英寸。已知今年卖出的 76 头一岁牛犊的 3 项平均指标为(50, 0.2, 54)‘&#xff0c;样本协差阵及其逆矩阵为 S [ 3.00 − 0.053 2.97 − 0.053 0…