Lazy与Suspense

Lazy 和 Suspense


1、React.lazy 定义

React.lazy 函数能让你像渲染常规组件一样处理动态引入(的组件)。

什么意思呢?其实就是懒加载。其原理就是利用es6 import()函数。这个import不是import命令

同样是引入模块,import命令是同步引入模块,而import()函数动态引入。

当 Webpack 解析到该语法时,它会自动地开始进行代码分割(Code Splitting),分割成一个文件,当使用到这个文件的时候会这段代码才会被异步加载。


(1) 为什么代码要分割

当你的程序越来越大,代码量越来越多。一个页面上堆积了很多功能,也许有些功能很可能都用不到,但是一样下载加载到页面上,所以这里面肯定有优化空间。就如图片懒加载的理论。

(2) import函数

//import 命令
import { add } from './math';

console.log(add(16, 26));

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

动态 import() 语法目前只是一个 ECMAScript (JavaScript) 提案, 而不是正式的语法标准。预计在不远的将来就会被正式接受。


(3) import函数示例

下面是import一个示例:

在test文件夹下新建两个文件

test.html代码如下:

<div id="root">
  页面无内容
</div>
<button id="btn">加载js</button>

<script>
  document.getElementById('btn').onclick=function(){
    import('./test.js').then(d=>{
      d.test()
    })
  }
</script>

test.js代码如下:

function test(){
  document.getElementById('root')
  root.innerHTML='页面变的有内容了'
}
export {test}

这时候打开web服务让页面以http的方式访问,http://192.168.1.2:8080/test.html

在chrome的开发者工具下的Network可以看到只请求了一个页面。

但是点击加载js,你会发现test.js会以动态的方式加入到代码中,同时执行了test函数,使页面的内容发生了变化。

React.lazy和常用的三方包react-loadable,都是使用了这个原理,然后配合webpack进行代码打包拆分达到异步加载,这样首屏渲染的速度将大大的提高。

由于React.lazy不支持服务端渲染,所以这时候react-loadable就是不错的选择。



2、如何使用React.lazy

下面示例代码使用create-react-app脚手架搭建:

//OtherComponent.js 文件内容

import React from 'react'
const OtherComponent = ()=>{
  return (
    <div>
      我已加载
    </div>
  )
}
export default OtherComponent

// App.js 文件内容
import React from 'react';
import './App.css';

//使用React.lazy导入OtherComponent组件
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function App() {
  return (
    <div className="App">
      <OtherComponent/>
    </div>
  );
}
export default App;

这是最简单的React.lazy,但是这样页面会报错。这个报错提示我们,在React使用了lazy之后,会存在一个加载中的空档期,React不知道在这个空档期中该显示什么内容,所以需要我们指定。接下来就要使用到Suspense

(1) Suspense

如果在 App 渲染完成后,包含 OtherComponent 的模块还没有被加载完成,我们可以使用加载指示器为此组件做优雅降级。这里我们使用 Suspense 组件来解决。

这里将App组件改一改

import React, { Suspense, Component } from 'react';
import './App.css';

//使用React.lazy导入OtherComponent组件
const OtherComponent = React.lazy(() => import('./OtherComponent'));

export default class App extends Component {
  state = {
    visible: false
  }
  render() {
    return (
      <div className="App">
        <button onClick={() => {
          this.setState({ visible: true })
        }}>
          加载OtherComponent组件
        </button>
        <Suspense fallback={<div>Loading...</div>}>
          {
            this.state.visible
              ?
              <OtherComponent />
              :
              null
          }
        </Suspense>
      </div>
    )
  }
}

我们指定了空档期使用Loading展示在界面上面,等OtherComponent组件异步加载完毕,把OtherComponent组件的内容替换掉Loading上。

为了演示我把chrome网络调到lower-end mobile,不然看不到loading出现。

可以从上面图片看出,当点击加载的时候,页面的head会插入``这段代码,发出一个get请求,页面开始显示loading,去请求2.chunk.js文件。

请求结束返回内容就是OtherComponent组件的内容,只是文件名称和文件内容经过webpack处理过。

注意:Suspense使用的时候,fallback一定是存在且有内容的, 否则会报错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Raccom

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值