react新版本的lazy和suspense实现组件懒加载和路由懒加载

来源:程序思维浏览:3841次
react16.6之前的版本没有路由懒加载需要自己手动实现,现在有了lazy和suspense可以轻松的做到路由懒加载现在咱们看看怎么实现吧:

咱们先来看看不用lazy和suspense如何实现路由懒加载:

1、建立AsyncComponent.js文件里面的代码:

import React, { Component } from "react";

export default function asyncComponent(importComponent) {
    class AsyncComponent extends Component {
        constructor(props) {
            super(props);

            this.state = {
                component: null
            };
        }
     async componentDidMount() {
            const { default: component } = await importComponent();
            this.setState({
                component: component
            });
        }
        render() {
            const C = this.state.component;
            return C ? <C {...this.props} /> : null;
        }
    }
    return AsyncComponent;
}


2、在router.js路由配置文件里面写入以下代码:

import asyncComponent from './components/async/AsyncComponent';

const IndexPage=asyncComponent(()=>import("./pages/index/index"));//用aysncComponent来包裹组件,实现路由懒加载

<Route path="/" exact component={IndexPage}></Route>

好了以上方案的好处是不需要考虑兼容性问题,16版本之后都兼容。

下面来看看lazy和suspense来实现路由懒加载吧:

组件懒加载

本演示将使用react-pdf。react-pdf是一个很棒的库,用于在浏览器、移动端和服务器上创建PDF文件。一般我们都在服务器上生成PDF,但是如果我们需要在客户端进行,则需要一个成本:包大小。

react-pdf代码

首先,假设我们的需求是在用户点击按钮时生成PDF文件。



其次,如果这是一个很大的web app以及这个功能可能是很小一部分,也许是用户不经常使用的功能。每次页面请求都会加载整个react-pdf代码就变得无意义了。

所以,我们非常需要一个延迟加载的解决方案。

预加载 VS 懒加载 展示

一个简易的PDFPreview组件

import React from "react";
import { PDFViewer, Document, Page, Text, View } from "@react-pdf/renderer";
import pdfstyles from "./pdfStyles";

// Create Document Component
const PDFPreview = ({ title }) => (
  <PDFViewer className="viewer" style={pdfstyles.viewer}>
    <Document>
      <Page size="A4" style={pdfstyles.page}>
        <View style={pdfstyles.section}>
          <Text style={pdfstyles.title}>{title}</Text>
          <Text>This is a text in a generated PDF file.</Text>
        </View>
      </Page>
    </Document>
  </PDFViewer>
);

export default PDFPreview;
添加样式

import { StyleSheet } from "@react-pdf/renderer";
const styles = StyleSheet.create({
  viewer: {
    padding: 0
  },

  page: {
    margin: 0,
    flexDirection: "row",
    backgroundColor: "#ffffff"
  },
  title: {
    fontSize: 30,
    marginBottom: 30
  },
  section: {
    margin: 10,
    padding: 10,
    flexGrow: 1
  }
});

export default styles;
预加载
让我们看看没有延迟加载的父组件

import React, { Component } from "react";
import PDFPreview from "./PDFPreview";

class App extends Component {
  state = {
    name: "",
    showPDFPreview: false
  };

  handleClick = () => this.setState({ showPDFPreview: true });

  handleNameChange = event => this.setState({ name: event.target.value });

  render() {
    const greeting = `Hello ${this.state.name}`;

    return (
      <div className="App">
        <input
          placeholder="Enter your name"
          type="text"
          onChange={this.handleNameChange}
        />

        <button onClick={this.handleClick}>Generate PDF</button>
        {this.state.showPDFPreview && <PDFPreview title={greeting} />}
      </div>
    );
  }
}

export default App;

在浏览器中将呈现以下视图



无论我们是否点击生成PDF,与其相关的所有代码都包含在应用包内了



这是一个开发环境。在打包之后,Size将显著缩小。尽管如此,我们还是没有最佳地分割代码。

懒加载
import React, { Component, Suspense } from "react";
const LazyPDFDocument = React.lazy(() => import("./PDFPreview"));

class App extends Component {
  state = {
    name: "",
    showPDFPreview: false
  };

  handleClick = () => this.setState({ showPDFPreview: true });

  handleNameChange = event => this.setState({ name: event.target.value });

  render() {
    const greeting = `Hello ${this.state.name}`;

    return (
      <div className="App">
        <input
          placeholder="Enter your name"
          type="text"
          onChange={this.handleNameChange}
        />

        <button onClick={this.handleClick}>Generate PDF</button>
        {this.state.showPDFPreview && (
          <Suspense fallback={<div>Loading...</div>}>
            <LazyPDFDocument title={greeting} />
          </Suspense>
        )}
      </div>
    );
  }
}

export default App;
我们只做了很小的改动:
第2行替换为:

const LazyPDFDocument = React.lazy(() => import("./PDFPreview"));
让我们看看React文档对React.lazy的说法:

React.lazy必须通过调用动态的import()加载一个函数,此时会返回一个Promise,并解析(resolve)为一个带有包含React组件的默认导出的模块。 - reactjs.org

因此如果的IE中使用,需要预先使用PolyfillPromise来实现动态import

在第27行,我们使用Suspense,它必须是延迟加载组件的父级(即React.lazy加载的组件只能在<React.Suspense>组件下使用)。当showPDFPreview设置为true时,LazyPDFDocument开始加载。

在子组件被解析之前,Suspense会显示由fallback属性提供的任何内容,且fallback为必带参数



路由懒加载

比如:router.js路由配置文件里面的代码:

import React,{lazy,Suspense} from 'react';
import {HashRouter as Router,Route} from 'react-router-dom';
const IndexPage=lazy(()=>import("./pages/index")); //使用lazy包裹组件,实现路由懒加载
const NewsPage=lazy(()=>import("./pages/news"));
const NewsDetailsPage=lazy(()=>import("./pages/news/details"));
class RouterComponent extends React.Component{
    render(){
        return (
            <React.Fragment>
                <Router>
                    <React.Fragment>
                        <Suspense fallback={<React.Fragment/>}> //使用Suspense包裹路由组件
                            <Route path="/" exact component={IndexPage}></Route>
                            <Route path="/news" exact component={NewsPage}></Route>
                            {/*<Route path="/news/details/:id/:title" component={NewsDetailsPage}></Route>*/}
                            <Route path="/news/details" component={NewsDetailsPage}></Route>
                        </Suspense>
                    </React.Fragment>
                </Router>
            </React.Fragment>
        )
    }
}

export default RouterComponent;

好了这样就能实现路由懒加载了。
精品好课
Vue2+Vue3+ES6+TS+Uni-app开发微信小程序从入门到实战视频教程
2021年最新Vue2+Vue3+ES6+TypeScript和uni-app开发微信小程序从入门到实战视频教程,本课程教你如何快速学会VUE和uni-app并应用到实战,教你如何解决内存泄漏,常用UI库的使用,自己...
jQuery视频教程从入门到精通
jquery视频教程从入门到精通,课程主要包含:jquery选择器、jquery事件、jquery文档操作、动画、Ajax、jquery插件的制作、jquery下拉无限加载插件的制作等等......
React实战视频教程仿京东移动端电商
React是前端最火的框架之一,就业薪资很高,本课程教您如何快速学会React并应用到实战,对正在工作当中或打算学习React高薪就业的你来说,那么这门课程便是你手中的葵花宝典。
最新完整React+VUE视频教程从入门到精,企业级实战项目
React和VUE是目前最火的前端框架,就业薪资很高,本课程教您如何快速学会React和VUE并应用到实战,教你如何解决内存泄漏,常用库的使用,自己封装组件,正式上线白屏问题,性能优化等。对正在工作当中或打算学习Re...
VUE2+VUE3视频教程从入门到精通(全网最全的Vue课程)
VUE是目前最火的前端框架之一,就业薪资很高,本课程教您如何快速学会VUE+ES6并应用到实战,教你如何解决内存泄漏,常用UI库的使用,自己封装组件,正式上线白屏问题,性能优化等。对正在工作当中或打算学习VUE高薪就...
HTML5视频播放器video开发教程
适用人群1、有html基础2、有css基础3、有javascript基础课程概述手把手教你如何开发属于自己的HTML5视频播放器,利用mp4转成m3u8格式的视频,并在移动端和PC端进行播放支持m3u8直播格式,兼容...
HTML5基础入门视频教程易学必会
HTML5基础入门视频教程,教学思路清晰,简单易学必会。适合人群:创业者,只要会打字,对互联网编程感兴趣都可以学。课程概述:该课程主要讲解HTML(学习HTML5的必备基础语言)、CSS3、Javascript(学习...
最新完整React视频教程从入门到精通纯干货纯实战
React是目前最火的前端框架,就业薪资很高,本课程教您如何快速学会React并应用到实战,教你如何解决内存泄漏,常用UI库的使用,自己封装组件,正式上线白屏问题,性能优化等。对正在工作当中或打算学习React高薪就...
收藏
扫一扫关注我们