本文主要是介绍React16源码: Suspense与lazy源码实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Suspense 与 lazy
1 )概述
- Suspense 是在 react16.6 提供的新 feature
- 用于加载的缓冲的内置组件
2 )示例程序
lazy.js
// lazy.js
import React from 'react'
export default () => <p>Lazy Comp</p>
主程序
import React, { Suspense, lazy } from 'react'const LazyComp = lazy(() => import('./lazy.js'))let data = ''
let promise = ''
function requestData() {if (data) return dataif (promise) throw promisepromise = new Promise(resolve => {setTimeout(() => {data = 'Data resolved'resolve()}, 2000)})throw promise
}function SuspenseComp() {const data = requestData()return <p>{data}</p>
}export default () => (<Suspense fallback="loading data"><SuspenseComp /><LazyComp /></Suspense>
)
- 示例的效果是先显示的是 loading data,然后再显示出来 Data resolved
- 最终 export出去的这个组件,它是一个 function component
- 里面使用了
Suspense
,然后给它一个 fallback 的 prop - 这就是我们看到的 loading data,里面是一个组件(SuspenseComp),也是一个function component
- 调用了一个 requestData 方法,它渲染的是一个p标签, 填充 data
- 里面使用了
- 可以在一个
Suspense
组件,下面渲染一个或者多个这种异步的组件- 有任何一个抛出了 promise以及在这个 promise relove 之前
- 都会显示这个 fallback里的内容
- 这就是 Suspense 组件的一个原理
- 其实它具体的内部实现是非常复杂的
- 注意,16.6版本的React只支持lazy就是异步加载组件
- 并没有很好的去支持我们的异步数据加载的功能
- 相关源码没有稳定,跟数据加载相关的是
Suspense
的功能后期发布 - 在后面的版本进行使用,当前版本是不推荐在生产环境使用
Suspense
支持 lazy组件,可以非常方便的实现异步组件加载- 配合webpack提供的 import 来实现这个功能
- 比如代码中,
const LazyComp = lazy(() => import('./lazy.js'))
- 这个 LazyComp 也被放到这个
Suspense
里面
- 在控制台的 network 面板里面,刷新一下
- 可以看到bundle.js 然后 2.chunk.js
- 这就是我们进行了一个异步加载组件,自动给我们区分的一个 js 文件
- 因为其实我们是在本地开发的,异步加载速度非常快
- 最终 LazyComp 跟 Data resolved 是一起显示出来的
- 如果在
Suspense
组件内部有多个组件,要等到所有的组件都resolved之后 - 它才会把fallback里面的内容移除,这是
Suspense
的一个特点 - 如果里面任何一个组件处于 pending 状态,它还是会显示 fallback
3 ) 源码探究
-
定位到 React.js, 找到
Suspense
import {REACT_SUSPENSE_TYPE,} from 'shared/ReactSymbols';import { lazy } from './ReactLazy';const React = {// ... 此处省略其他lazy,// ... 此处省略其他Suspense: REACT_SUSPENSE_TYPE}
- 看到
Suspense
它是一个常量,就是一个REACT_SUSPENSE_TYPE
,本质上只是一个Symbol - 而 lazy 就不是一个Symbol 了
- 我们可以看到
import { lazy } from './ReactLazy';
- 看到
-
基于这个,定位到 ReactLazy.js 查看
lazy
源码/*** Copyright (c) Facebook, Inc. and its affiliates.** This source code is licensed under the MIT license found in the* LICENSE file in the root directory of this source tree.*/import type {LazyComponent, Thenable} from 'shared/ReactLazyComponent';import {REACT_LAZY_TYPE} from 'shared/ReactSymbols';export function lazy<T, R>(ctor: () => Thenable<T, R>): LazyComponent<T> {return {$$typeof: REACT_LAZY_TYPE,_ctor: ctor,// React uses these fields to store the result._status: -1,_result: null,}; }
-
它是一个方法
export function lazy
,并接收一个方法lazy<T, R>(ctor: () => Thenable<T, R>): LazyComponent<T>
- 它指定这个传入的参数,这个参数是一个方法,并且它要返回一个
Thenable
类型的对象 Thenable
是 Promise 这样的一个对象,它具有.then
方法
-
最终,返回的是一个 lazy component
$$typeof
,值为REACT_LAZY_TYPE
_ctor
就是我们传递进来的回调函数- 在react渲染的过程当中,渲染到 lazy component 的时候
- 会去调用这个
_ctor
回调,并返回一个 Thenable 的对象(Promise对象) - 这个时候Promise是处于 pending 状态的,对应的是值是 -1
_status
用来记录当前这个Thenable
的对象,所处的状态- 后续达到了resolved 或者是 rejected 的这两种状态的时候,这个 _status 会变化
- 让后期进行渲染的时候可以进行不一样的处理
_result
Promise结果- 用来记录这个Thenable对象,它 resolve 之后返回的那个属性
- 在 lazy 里面,最终的组件会挂载到这个
_result
- 后续渲染这个 lazy 组件的时候,直接拿
_result
里面的组件渲染就可以了
这篇关于React16源码: Suspense与lazy源码实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!