【React】 lazy 和 Suspense

一、import() 函数

  • 同样是引人模块,import命令是同步引人模块,而import ()函数动态引入
// `math.js`文件
const add = (x, y) => {
    return x + y;
}
export default add;
//import 命令
import { add } from './math';

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

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

案例:

  • 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的方式访问
  • 我们在chrome的开发者工具下的Network可以看到只请求了一个页面。

在这里插入图片描述

  • 但是当我们点击加载js,你会发现test.js会以动态的方式加入到代码中,同时执行了test函数,使页面的内容发生了变化。
    在这里插入图片描述

二、React.lazy

代码分割:

  • 当Webpack 解析到该语法时,它会自动地开始进行代码分割,分割成一个文件,当使用到这个文件的时候才会被异步加载
  • 当你的程序越来越大,代码量越来越多。一个页面上堆积了很多功能,也许有些功能很有可能都用不到,但是一样下载到页面上,所以这里面肯定有优化空间。比如图片懒加载
  • React.lazy函数能让你像渲染常规组件一样处理动态引用的组件
  • 什么意思呢,其实就是懒加载。其原理就是利用ES6 import()函数。
// 这个组件是动态加载的
const SomeComponent = React.lazy(() => import('./SomeComponent'));
  • React.lazy和常用的三方包react-loadable,都是使用了这个原理,然后配合webpack进行代码打包拆分达到异步加载,这样首屏渲染的速度将大大的提高。
  • 由于React.lazy不支持服务端渲染,所以这时候react-loadable就是不错的选择。

三、React.Suspense

React.Suspense 可以指定加载指示器(loading indicator),以防其组件树中的某些子组件尚未具备渲染条件。目前,懒加载组件是 <React.Suspense> 支持的唯一用例:

// 该组件是动态加载的
const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    // 显示 <Spinner> 组件直至 OtherComponent 加载完成
    <React.Suspense fallback={<Spinner />}>
      <div>
        <OtherComponent />
      </div>
    </React.Suspense>
  );
}

3.1、lazy 不用 Suspense(报错)

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

  • OtherComponent.jsx 文件内容

// 普通的子组件
import React from 'react';
const OtherComponent = ()=>{
    return(
        <div>我已加载</div>
    )
}
  • App.jsx 文件内容
import React, {Component} from 'react';
const OtherComponent = React.lazy(()=>import('./OtherComponent'));
class App extends Component{
    constructor(props){
        super(props);
        this.state = {};
    }
    render(){
        return (
            <div>
                <OtherComponent />
            </div>
        )
    }
}
export default App;
  • index.js 文件内容
import ReactDOM  from 'react-dom'
import App from './Lazy/App';

ReactDOM.render(
    <App  />,
    document.getElementById('root')
)
  • 运行结果:
    在这里插入图片描述
    这是最简单的React.lazy,但是这样页面会报错。这个报错提示我们,在React使用了lazy之后,会存在一个加载中的空档期,React不知道在这个空档期中该显示什么内容,所以需要我们指定。接下来就要使用到Suspense

3.2、lazy 使用 Suspense(推荐)

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

  • 这里将App组件改一改
import React, {Suspense,Component} from 'react';
const OtherComponent = React.lazy(()=>import('./OtherComponent'));
class App extends Component{
    constructor(props){
        super(props);
        this.state = {
            visible:false
        };
    }
    render(){
        return (
            <div>
                <button onClick={() => {
          this.setState({ visible: true })
        }}>
          加载OtherComponent组件
        </button>
        <Suspense fallback={<div>Loading...</div>}>
          {
            this.state.visible
              ?
              <OtherComponent />
              :
              null
          }
        </Suspense>
            </div>
        )
    }
}
export default App;
  • 我们指定了空档期使用Loading展示在界面上面,等OtherComponent组件异步加载完毕,把OtherComponent组件的内容替换掉Loading上。

在这里插入图片描述
在这里插入图片描述

  • 可以从上面图片看出,当点击加载的时候,页面的head会插入``这段代码,发出一个get请求,页面开始显示loading,去请求2.chunk.js文件
  • 请求结束返回内容就是OtherComponent组件的内容,只是文件名称和文件内容经过webpack处理过
  • 注意:Suspense使用的时候,fallback一定是存在且有内容的, 否则会报错。
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一颗不甘坠落的流星

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

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

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

打赏作者

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

抵扣说明:

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

余额充值