uploadhub的技术博客 uploadhub的技术博客
首页
  • 学习笔记

    • 《HTML5和CSS3篇》
    • 《JavaScript基础篇》
    • 《JavaScript高级篇》
    • 《Ajax篇》
    • 《JavaScript模块化篇》
    • 《Node.js篇》
    • 《MongoDB篇》
    • 《Promise篇》
    • 《Git篇》
  • 《Vue2+Vue3篇》
  • 《React篇》
  • 一面-基础
  • 二三面-进阶
关于我
  • 分类
  • 标签
  • 归档

uploadhub

首页
  • 学习笔记

    • 《HTML5和CSS3篇》
    • 《JavaScript基础篇》
    • 《JavaScript高级篇》
    • 《Ajax篇》
    • 《JavaScript模块化篇》
    • 《Node.js篇》
    • 《MongoDB篇》
    • 《Promise篇》
    • 《Git篇》
  • 《Vue2+Vue3篇》
  • 《React篇》
  • 一面-基础
  • 二三面-进阶
关于我
  • 分类
  • 标签
  • 归档
  • Vue相关

  • React相关

    • 1.React基本使用
    • 2.React原理
      • 1.函数式编程
      • 2.vdom和diff
      • 3.JSX本质是什么
      • 4.合成事件
        • 4.1 为何要合成事件机制
      • 5.setState batchUpdate
        • 5.1 setState主流程
        • 5.2 batchUpdate机制
        • 5.2.1 setState是同步还是异步
        • 5.2.2 哪些能命中batchUpdate机制
        • 5.2.3 哪些不能命中batchUpdate机制
        • 5.3 transaction(事务)机制
      • 6.组件渲染过程
        • 6.1 前情回顾
        • 6.1.1 Vue组件渲染和更新过程
        • 参考链接
        • 6.1.2 JSX本质和vdom
        • 6.1.3 dirtyComponents
        • 6.2 正式内容
        • 6.2.1 组件渲染过程
        • 6.2.2 组件更新过程
        • 6.2.3 更新的两个阶段
        • 6.2.4 可能会有性能问题
        • 6.2.5 解决方案-fiber
        • 6.2.6 关于fiber
    • 3.React面试真题演练
    • 4.React Hooks
  • Webpack和Babel

  • 项目设计
  • 项目流程
  • 二三面-进阶
  • React相关
uploadhub
2022-05-28
目录

2.React原理

# 1.函数式编程

  1. 一种编程范式,概念比较多

  2. 纯函数

  3. 不可变值

# 2.vdom和diff

  1. h函数

  2. vnode数据结构

  3. patch函数

  4. 只比较同一层级,不跨级比较

  5. tag不相同,则直接删掉重建,不再深度比较

  6. tag和key,两者都相同,则认为是相同节点,不再深度比较

  7. Vue2.x Vue3.0 React三者实现vdom细节都不同

  8. 核心概念和实现思路,都一样

  9. 面试主要考察后者,不用全部掌握细节

# 3.JSX本质是什么

  1. JSX等同于Vue模板

  2. Vue模板不是html

  3. JSX也不是JS

https://www.babeljs.cn/

// JSX 基本用法
const imgElem = <div id="div1">
    <p>some text</p>
    <img src={imgUrl}/>
</div>

// JSX style
const styleData = { fontSize: '30px',  color: 'blue' }
const styleElem = <p style={styleData}>设置 style</p>

// JSX 加载组件
const app = <div>
    <Input submitTitle={onSubmitTitle}/>
    <List list={list}/>
</div>

// JSX 事件
const eventList = <p onClick={this.clickHandler}>
    some text
</p>

// JSX list
const listElem = <ul>{this.state.list.map((item, index) => {
    return <li key={item.id}>index {index}; title {item.title}</li>
})}</ul>


// 总结
React.createElement('div', null, [child1, child2, child3])
React.createElement('div', {...}, child1, child2, child3)
React.createElement(List, null, child1, child2, '文本节点')
// h 函数
// 返回 vnode
// patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
  1. React.createElement即h函数,返回vnode

  2. 第一个参数,可能是组件,也可能是html tag

  3. 组件名,首字母必须大写(React规定)

image-20221007233814959

# 4.合成事件

  1. 所有事件挂载到document上

  2. event不是原生的,是SyntheticEvent合成事件对象

  3. 和Vue事件不同,和DOM事件也不同

1. event 是 SyntheticEvent ,模拟出来 DOM 事件所有能力
2. event.nativeEvent 是原生事件对象
3. 所有的事件,都被挂载到 document 上
4. 和 DOM 事件不一样,和 Vue 事件也不一样
1
2
3
4

合成事件-图示改

# 4.1 为何要合成事件机制

  1. 更好的兼容性和跨平台

  2. 挂载到document,减少内存消耗,避免频繁解绑

  3. 方便事件的统一管理(如事务机制)

# 5.setState batchUpdate

  1. 有时异步(普通使用),有时同步(setTimeout、DOM事件)

  2. 有时合并(对象形式),有时不合并(函数形式)

  3. 后者比较好理解(像Object.assign),主要讲解前者

# 5.1 setState主流程

setState主流程

image-20221008154920135

# 5.2 batchUpdate机制

//此时setState相当于普通的异步
class ListDemo extends React.Component {
    constructor(props) {...}
	render() {...}
	increase = ()=>{
		//开始:处于 batchUpdate 
		// isBatchingUpdates = true 
        this.setState({
			count:this.state.count + 1 
        })
		//结束
		//isBatchingUpdates = false 
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//模拟setTimeout下的batchUpdates机制,此时setState相当于同步
class ListDemo extends React.Component {
    constructor(props) {...}
	render() {...}
	increase = ()=>{
		//开始:处于 batchUpdate 
		// isBatchingUpdates = true 
        setTimeout(()=>{
            //此时isBatchUpdates是false
            this.setState({
                count:this.state.count + 1 
            })
        })
		//结束
		//isBatchingUpdates = false 
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//模拟DOM事件下的batchUpdates机制,此时setState相当于同步
componentDidMount() {
	//开始:处于 batchUpdate 
    //isBatchingUpdates = true
	document.body.addEventListener('cliçk', ()={
		//此时 isBatchingUpdates 是 false
		this.setState({
			count:this.state.count + 1 
    	})
		console.log('count in body event', this.state.count) 
	})
	//结束
	//isBatchingUpdates = false
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 5.2.1 setState是同步还是异步

  1. setState无所谓异步还是同步

  2. 看是否能命中batchUpdate机制

  3. 判断isBatchingUpdates

# 5.2.2 哪些能命中batchUpdate机制

  1. 生命周期(和它调用的函数)

  2. React中注册的时间(和它调用的函数)

  3. React可以“管理”入口

# 5.2.3 哪些不能命中batchUpdate机制

  1. setTimeout setInterval等(和它调用的函数)

  2. 自定义的DOM时间(和它调用的函数)

  3. React“管不到”的入口

# 5.3 transaction(事务)机制

//transaction事务机制示例
class ListDemo extends React.Component {
    constructor(props) {...}
	render() {...}
	increase = ()=>{
		//开始:处于 batchUpdate 
		// isBatchingUpdates = true 
        
        //其他任何操作
        
        
		//结束
		//isBatchingUpdates = false 
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 			/*React源代码中给出的描述Transaction事务机制的工作原理的草图*/
					wrappers (injected at creation time)
                                      +        +
                                      |        |
                    +-----------------|--------|--------------+
                    |                 v        |              |
                    |      +---------------+   |              |
                    |   +--|    wrapper1   |---|----+         |
                    |   |  +---------------+   v    |         |
                    |   |          +-------------+  |         |
                    |   |     +----|   wrapper2  |--------+   |
                    |   |     |    +-------------+  |     |   |
                    |   |     |                     |     |   |
                    |   v     v                     v     v   | wrapper
                    | +---+ +---+   +---------+   +---+ +---+ | invariants
 perform(anyMethod) | |   | |   |   |         |   |   | |   | | maintained
 +----------------->|-|---|-|---|-->|anyMethod|---|---|-|---|-|-------->
                    | |   | |   |   |         |   |   | |   | |
                    | |   | |   |   |         |   |   | |   | |
                    | |   | |   |   |         |   |   | |   | |
                    | +---+ +---+   +---------+   +---+ +---+ |
                    |  initialize                    close    |
                    +-----------------------------------------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//transaction使用示例
transaction.initialize = function() { 
    console.log('initialize')
}

transaction.close = function() { 
    console.log('close')
}

function method(){ 
    console. log( 'abc' ) 
}
transaction.perform(method)
//依次输出'initialize'、'abc'、'close'
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 6.组件渲染过程

  1. JSX如何渲染为页面

  2. setState之后如何更新页面

  3. 面试考察全流程

# 6.1 前情回顾

# 6.1.1 Vue组件渲染和更新过程

Vue2版本示意图

Vue2的组件渲染和更新过程示意图

Vue3版本示意图

Vue3的组件渲染和更新过程示意图

# 参考链接
  1. [官网-Vue3-渲染管线](渲染机制 | Vue.js (vuejs.org) (opens new window))
  2. 官网-Vue2-深入响应式原理 (opens new window)

# 6.1.2 JSX本质和vdom

  1. JSX即createElement函数

  2. 执行生成vnode

  3. patch(elem,vnode)和patch(vnode,newVnode)

# 6.1.3 dirtyComponents

setState主流程

# 6.2 正式内容

# 6.2.1 组件渲染过程

  1. props state

  2. render()生成vnode

  3. patch(elem,vnode)

# 6.2.2 组件更新过程

  1. setState(newState) --> dirtyComponents(可能有子组件)

  2. render()生成newVnode

  3. patch(vnode,newVnode)

# 6.2.3 更新的两个阶段

上述的patch被拆分为两个阶段:

  1. reconciliation阶段 - 执行diff算法,纯JS计算
  2. commit阶段 - 将diff结果渲染DOM

# 6.2.4 可能会有性能问题

  1. JS是单线程,且和DOM渲染共用一个线程

  2. 当组件足够复杂,组件更新时计算和渲染都压力大

  3. 同时若再有DOM操作需求(动画,鼠标拖拽等),将卡顿

# 6.2.5 解决方案-fiber

  1. 将reconciliation阶段进行任务拆分(commit无法拆分)

  2. DOM需要渲染时暂停,空闲时恢复

  3. window.requestIdleCallback

# 6.2.6 关于fiber

  1. React内部运行机制,开发者体会不到

  2. 了解背景和基本概念即可

#面试#React
1.React基本使用
3.React面试真题演练

← 1.React基本使用 3.React面试真题演练→

最近更新
01
HTTP协议及缓存机制
05-28
02
开发环境
05-28
03
JS基础知识(一)-变量类型和计算
05-28
更多文章>
Theme by Vdoing | Copyright © 2021-2023 uploadhub | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式