React16源码: Suspense与lazy源码实现

2024-01-02 05:04

本文主要是介绍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 会变化
      • 让后期进行渲染的时候可以进行不一样的处理
    • _resultPromise结果
      • 用来记录这个Thenable对象,它 resolve 之后返回的那个属性
      • 在 lazy 里面,最终的组件会挂载到这个 _result
      • 后续渲染这个 lazy 组件的时候,直接拿 _result 里面的组件渲染就可以了

这篇关于React16源码: Suspense与lazy源码实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/561407

相关文章

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

Python实现字典转字符串的五种方法

《Python实现字典转字符串的五种方法》本文介绍了在Python中如何将字典数据结构转换为字符串格式的多种方法,首先可以通过内置的str()函数进行简单转换;其次利用ison.dumps()函数能够... 目录1、使用json模块的dumps方法:2、使用str方法:3、使用循环和字符串拼接:4、使用字符

Linux下利用select实现串口数据读取过程

《Linux下利用select实现串口数据读取过程》文章介绍Linux中使用select、poll或epoll实现串口数据读取,通过I/O多路复用机制在数据到达时触发读取,避免持续轮询,示例代码展示设... 目录示例代码(使用select实现)代码解释总结在 linux 系统里,我们可以借助 select、

Linux挂载linux/Windows共享目录实现方式

《Linux挂载linux/Windows共享目录实现方式》:本文主要介绍Linux挂载linux/Windows共享目录实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录文件共享协议linux环境作为服务端(NFS)在服务器端安装 NFS创建要共享的目录修改 NFS 配

通过React实现页面的无限滚动效果

《通过React实现页面的无限滚动效果》今天我们来聊聊无限滚动这个现代Web开发中不可或缺的技术,无论你是刷微博、逛知乎还是看脚本,无限滚动都已经渗透到我们日常的浏览体验中,那么,如何优雅地实现它呢?... 目录1. 早期的解决方案2. 交叉观察者:IntersectionObserver2.1 Inter

Spring Gateway动态路由实现方案

《SpringGateway动态路由实现方案》本文主要介绍了SpringGateway动态路由实现方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录前沿何为路由RouteDefinitionRouteLocator工作流程动态路由实现尾巴前沿S