React16源码: ConcurrentMode的使用及源码实现
2024-01-01 20:46:34
ConcurrentMode
1 ) 概述
ConcurrentMode
是 React 16 出来的一个最令人振奋的功能- 在2018年年初是
Async Mode
,在发布了16.6之后,名字进行了更新 - 然后改成了 ConcurrentMode,中间的API有一个过渡的版本,后续会提到
- 它其实是 React 16 之前已有的概念了
- 其目标是让 React 的整体渲染过程能够进行一个优先级的排比
- 并且让整体的一个渲染的过程是能够中断的
- 它就可以进行一个任务的调度,提升 cpu 性能
- 因为 js 是一个单线程的语言, 如果我们执行更新占用了非常长的时间
- 比如,浏览器执行一些动画的渲染中间,被进程占用执行其他操作, 时间被拉长,动画就变得比较卡顿
- 或者是我们在进行一些input的输入的时候,响应会比较的卡,因为这个时候 js 正在运行react的更新
- 在这种时候,React 让我们能够去区分一些优先级比较高和比较低的任务
- 在进行一个 React更新的过程当中,它优先执行优先级高的任务
- 在等浏览器把这些优先级高的任务,执行完之后,它有空余的时间的时候,再来执行优先级较低的任务
2 ) 实例演示
// ConcurrentMode 以前叫做 unstable_ConcurrentMode // 这个就是上面说的 过渡 API
import React, { unstable_ConcurrentMode as ConcurrentMode } from 'react'; // react 16.6 版本
// import React, { ConcurrentMode } from 'react'; // react 16.7 版本
// 这个会强制执行某个更新操作时, 使用优先级最高方式进行更新
import { flushSync } from 'react-dom;
import './index.css'
class Parent extends React.Component {
state = {
async: true,
num: 1,
length: 2000,
}
componentDidMount() {
this.interval = setInterval(() => {
this.updateNum()
}, 200)
}
componentWillUnmount() {
// 别忘了清除interval
if (this.interval) {
clearInterval(this.interval)
}
}
updateNum() {
const newNum = this.state.num === 3 ? 0 : this.state.num + 1
if (this.state.async) {
this.setState({
num: newNum,
})
} else {
flushSync(() => {
this.setState({
num: newNum,
})
})
}
}
render() {
const children = []
const { length, num, async } = this.state
for (let i = 0; i < length; i++) {
children.push(
<div className="item" key={i}>
{num}
</div>,
)
}
return (
<div className="main">
async:{' '}
<input
type="checkbox"
checked={async}
onChange={() => flushSync(() => this.setState({ async: !async }))}
/>
<div className="wrapper">{children}</div>
</div>
)
}
}
export default () => (
<ConcurrentMode>
<Parent />
</ConcurrentMode>
)
- 上面
unstable_ConcurrentMode
是ConcurrentMode
的过渡版本- 在后续16.7 实验版本的源码中是这样判断的
var enableStableConcurrentModeAPIS = true // 注意这里是 true // ... 中间省略很多代码 if (enableStableConcurrentModeAPIS) { React.ConcurrentMode = REACT_CONCURRENT_MODE_TYPE; React.Profiler = REACT_POFILER_TYPE; } else { React.unstable_ConcurrentMode = REACT_CONCURRENT_MODE_TYPE; React.unstable_Profiler = REACT_POFILER_TYPE; }
- 在后续16.7 实验版本的源码中是这样判断的
- 关于上面的
flashSync
这个API- 它会强制我们在执行某一个更新操作的时候,使用优先级最高的方式去进行一个更新
- 在
ConcurrentMode
有一个特性- 我们在一个子树当中渲染了
ConcurrentMode
之后 - 它下面的所有的节点产生的更新,就是一个低优先级的更新
- 上面的示例,把整体渲染都放在这个
ConcurrentMode
下面, 所以这个组件它产生的所有更新 - 就是我们通过 setState 这种方式去创建的这种更新, 它都是处于一个低优先级的
- 我们在一个子树当中渲染了
- 上面的示例,展示了低优先级和高优先级它的一个区别
- 使用
flashSync
来提高整体的一个优先级
- 使用
- 上面示例程序渲染了有2千个节点
- 每个节点里面的数字是一直在变的,在这个过程当中
- 我们又给浏览器增加了一个持续性的动画,就是让整体的一个区域左右的移动
- 动画的优先级明显是较高的
- 主要关注
updateNum
这个函数的 if else 判断 - 就是我们通过一个 checkbox 来切换 async 的情况
- 当结果为 false 时,调用
flashSync
,因为它是一个优先级较高的任务,强制立马更新掉 - 效果就是: 数字变化特别快,但是动画运动就特别卡
- 当结果为 false 时,调用
- 这就是 异步模式 (async mode) 和 同步模式(sync mode) 的一个本质的区别
- 在 async mode 下面会区分优先级,让整体的动画能够看起来更流畅一点
- 在 sync mode 下面,它没有一个优先级的区别,所以它们都是一起进行的
- 在进行更新的时候,导致我们整个动画也会变得一卡一卡的感觉
3 )源码探究
在 React.js 中, 看一下 ConcurrentMode 的源码是什么
import {
REACT_CONCURRENT_MODE_TYPE,
REACT_FRAGMENT_TYPE,
REACT_PROFILER_TYPE,
REACT_STRICT_MODE_TYPE,
REACT_SUSPENSE_TYPE,
} from 'shared/ReactSymbols';
// ... 省略其他
// 最后
if (enableStableConcurrentModeAPIs) {
React.ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;
React.Profiler = REACT_PROFILER_TYPE;
} else {
React.unstable_ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;
React.unstable_Profiler = REACT_PROFILER_TYPE;
}
- 在这里面 ConcurrentMode 它等于的是一个常量,它是一个
REACT_CONCURRENT_MODE_TYPE
- 是从
shared/ReactSymbols
文件中导入的一个类型,本质是一个 Symbolexport const REACT_CONCURRENT_MODE_TYPE = hasSymbol ? Symbol.for('react.concurrent_mode') : 0xeacf;
- 我们自己写组件的时候,我们都知道里面会有特别多的一些东西,我们要写一些 state
- 比如,业务逻辑 或者在 function component 里面至少渲染一些东西
- 但是我们这个组件它就是一个简单的 Symbol,没有任何其他的东西
- 目前,先不去探究它如何来承载其他组件的
文章来源:https://blog.csdn.net/Tyro_java/article/details/135327299
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!