Suspense和lazy()都是react中比较新的特性,在项目中使用还比较少,但是学习一下有助于在后面的项目中使用,同样可以一窥React未来的发展方向

React.lazy()

概括

顾名思义lazy()方法是用来对项目代码进行分割,懒加载用的.只有当组件被加载,内部的资源才会导入

为什么需要懒加载

在React的项目中import导入其他组件和库都是默认在初始直接导入的,webpack等打包工具会将import导入的文件直接合并到一个大文件中,如果项目很大,打包完后初始化加载时需要加载的文件会很大,这时候就需要代码分割

官方文档中的例子

项目中:

// app.js
import { add } from './math.js';
console.log(add(16, 26)); // 42
// math.js
export function add(a, b) {
  return a   b;
}

打包后

function add(a, b) {
  return a   b;
}
console.log(add(16, 26)); // 42

如何进行代码分割

在你的应用中引入代码分割的最佳方式是通过动态 import() 语法,这是官方文档中说的

动态import例子:

静态导入:

import { add } from './math';
console.log(add(16, 26));

动态导入:

import("./math").then(math => {
  console.log(math.add(16, 26));
});

使用了动态导入之后,webpack检测到这种语法会自动代码分割,也就是压缩到两个文件里

React.lazy()就是对这个种动态导入方式的优化方法

使用:

const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
  return (
    // Displays <Spinner> until OtherComponent loads
    <React.Suspense fallback={<Spinner />}>
      <div>
        <OtherComponent />
      </div>
    </React.Suspense>
  );
}

发现没有原来的动态导入写法像 Promise的写法链式调用,现在动态导入的方式,有点类似于Async写出来是同步使用的,可以直接讲返回的Promise对象作为组件使用,当这个组件pending是显示的是Suspense中fallback的内容,只有resolve才显示加载好的组件.

所以可以看出Suspense和React.lazy()需要结合在一起用,否则会报错缺少Placeholder UI`

Suspense

Suspense的英文意思是悬念,悬停**,Suspense的作用就是在遇到异步请求或者异步导入组件的时候等待请求和导入完成再进行渲染,**相比普通的组件, 我们是要求render是一个纯函数,一旦开始渲染不会等待,而有了Suspense后我们可以再render过程中写一部代码.

Suspense应用场景

Subspense存在两种应用场景,第一种就是动态导入组件(如上),一种就是异步请求数据(暂时不支持,大概16.9版本)

动态导入组件

动态导入组件上面的例子就是上面的代码片段,就是当这个组件pending是显示的是Suspense中fallback的内容,只有resolve才显示加载好的组件,所以fallback不能为空

优点

好处在于我们可以不用创建一些组件状态的变量来控制是否显示loading画面和真正组件,这部分逻辑直接由Suspense内部实现. 而且还有一种场景就是当一个父组件中,有多个动态加载的组件,Suspense可以直接将loading状态聚合,只有当所有组件加载完成才显示,这里免去了复杂的逻辑判断.

数据请求后渲染页面

Suspense暂时还不支持数据请求后渲染, 预计是在16.9版本也就是2019年年中发布,但是以及有了实例使用的方法,下面这里就是官方的示例代码,这里做一些翻译解释

// unstable_createResource这个就是一个封装的请求数据的插件,不用太清楚类似于fetch
import {unstable_createResource} from 'react-cache';
// 声明请求数据的方法
const TodoResource = unstable_createResource(fetchTodo);
//内部请求TodoResource.read(props.id) 就是异步请求数据
function Todo(props) {
  // Suspends until the data is in the cache
  const todo = TodoResource.read(props.id);
  return <li>{todo.title}</li>;
}
function App() {
  return (
    // 只有当两个Todo内部的异步请求都完成后才能渲染出来,否则渲染<Spinner/>
    <React.Suspense fallback={<Spinner />}>
      <ul>
        {/* Siblings fetch in parallel */}
        <Todo id="1" />
        <Todo id="2" />
      </ul>
    </React.Suspense>
  );
}

这就是Suspense请求数据时的使用的方法,同样解决了loading状态的问题,相当于再render过程中加入了异步副作用操作,再普通的组件中异步操作是不起作用的,因为先渲染完,异步数据才会返回,这时候已经渲染完了.

Suspense实现原理

Subspense的实现主要就是利用了**ComponentDidCatch这个生命周期,这个什么周期就是用来捕获子组件树中的任何Javascript异常**

源码就不分析了,这里说一下大概的流程步骤:

  • 父组件渲染到子组件时发现异步请求,直接抛出错误,捕获的结果是一个Promise对象
  • ComponentDidCatch捕获这个Promise对象,pending状态下渲染fallback的
  • 当resolve时重新render,遇到下一个异步请求重复上面操作
  • 直到整个父组件的抛出的promise对象都为resolve,将loading替换为真正的组件.

总结

Suspense其实就是将原来放在外面处理的异步请求也就是副作用放到渲染过程中进行操作,这样render这个函数就不再是纯函数了,但是非常直观方便,不需要再用很多状态来控制loading显示,而异步请求的结果无法预测会导致很多bug.

等到Suspense支持数据请求的场景时,我会考虑把它运用到自己的项目中, 感觉确实方便很多本来就觉得Loading状态有点多余,虽然现在用的是Dva,会自动给effect创建loading状态的,还不是特别需要.

以上为个人经验,希望能给大家一个参考,也希望大家多多支持Devmax。

React中Suspense及lazy()懒加载及代码分割原理和使用方式的更多相关文章

  1. ios – React native链接到另一个应用程序

    如果是错误的,有人知道如何调用正确的吗?

  2. ios – React Native – 在异步操作后导航

    我正在使用ReactNative和Redux开发移动应用程序,我正面临着软件设计问题.我想调用RESTAPI进行登录,如果该操作成功,则导航到主视图.我正在使用redux和thunk所以我已经实现了异步操作,所以我的主要疑问是:我应该把逻辑导航到主视图?我可以直接从动作访问导航器对象并在那里执行导航吗?.我对组件中的逻辑没有信心.似乎不是一个好习惯.有没有其他方法可以做到这一点?

  3. 在ios中使用带有React Native(0.43.4)的cocoapods的正确方法是什么?

    我已经挖掘了很多帖子试图使用cocoapods为本地ios库设置一个反应原生项目,但我不可避免地在#import中找到了丢失文件的错误.我的AppDelegate.m文件中的语句.什么是使用反应原生的可可豆荚的正确方法?在这篇文章发表时,我目前的RN版本是0.43.4,而我正在使用Xcode8.2.1.这是我的过程,好奇我可能会出错:1)

  4. ios – React Native WebView滚动行为无法按预期工作

    如何确保滚动事件的行为与ReactNative应用程序中的浏览器相同?

  5. ios – React Native – BVLinearGradient – 找不到’React/RCTViewManager.h’文件

    谢谢.解决方法几天前我遇到了完全相同的问题.问题是在构建应用程序时React尚未链接.试试这个:转到Product=>Scheme=>管理方案…=>点击你的应用程序Scheme,然后点击Edit=>转到Build选项卡=>取消选中ParallelizeBuild然后点击标志添加目标=>搜索React,选择第一个名为React的目标,然后单击Add然后在目标列表中选择React并将其向上拖动到该列表中的第一个.然后转到Product=>再次清理并构建项目.这应该有所帮助.

  6. ios – React Native – NSNumber无法转换为NSString

    解决方法在你的fontWeight()函数中也许变成:

  7. ios – React native error – react-native-xcode.sh:line 45:react-native:command not found命令/ bin/sh失败,退出代码127

    尝试构建任何(新的或旧的)项目时出现此错误.我的节点是版本4.2.1,react-native是版本0.1.7.我看过其他有相同问题的人,所以我已经更新了本机的最新版本,但是我仍然无法通过xcode构建任何项目.解决方法要解决此问题,请使用以下步骤:>使用节点版本v4.2.1>cd进入[你的应用]/node_modules/react-native/packager>$sh./packager.s

  8. 反应原生 – 如何通过Xcode构建React Native iOS应用程序到设备?

    我试图将AwesomeProject应用程序构建到设备上.构建成功并启动屏幕显示,但后来我看到一个红色的“无法连接到开发服务器”屏幕.它表示“确保节点服务器正在运行–从Reactroot运行”npmstart“.看起来节点服务器已经运行,因为当我做npm启动时,我收到一个EADDRINUSE消息,表示该端口已经在使用.解决方法从设备访问开发服务器您可以使用开发服务器快速迭代设备.要做到这一点,你的

  9. 静音iOS推送通知与React Native应用程序在后台

    我有一个ReactNative应用程序,我试图获得一个发送到JavaScript处理程序的静默iOS推送通知.我看到的行为是AppDelegate中的didReceiveRemoteNotification函数被调用,但是我的JavaScript中的处理程序不会被调用,除非应用程序在前台,或者最近才被关闭.我很困惑的事情显然是应用程序正在被唤醒,并且它的didReceiveRemoteNotifi

  10. 如何为iOS的React Native设置分析

    所以我已经完成了一个针对iOS的ReactNative项目,但是我想在其中分析.我尝试了react-native-google-analytics软件包,但是问题阻止了它的正常工作.此外,react-native-cordova-plugin软件包只适用于Android,因此插入Cordova插件进行分析的能力现在已成为问题.我也没有Swift/ObjectiveC的经验,所以将完全失去GA的插入.有没有人有任何建议如何连接GoogleAnalytics的ReactNativeforiOS?

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部