内容简介:之前写过一篇传统的 React 异步组件基本都靠自己实现,自己写一个专门的 React 组件加载函数作为异步组件的实现工具,通过2018 年 10 月 23 号,React 发布了v16.6 版本,新版本中有个新特性叫
之前写过一篇 Vue 异步组件的文章 ,最近在做一个简单项目的时候又想用到 React 异步组件,所以简单地了解了一下使用方法,这里做下笔记。
传统的 React 异步组件基本都靠自己实现,自己写一个专门的 React 组件加载函数作为异步组件的实现工具,通过 import()
动态导入,实现异步加载,可以参考 【翻译】基于 Create React App路由4.0的异步组件加载(Code Splitting) 这篇文章。这样做的话还是要自己写一个单独的加载组件,有点麻烦。于是想找个更简单一点的方式,没想到真给找到了: Async React using React Router & Suspense ,这篇文章讲述了如何基于 React Router 4 和 React 的新特性快速实现异步组件按需加载。
2018 年 10 月 23 号,React 发布了v16.6 版本,新版本中有个新特性叫 lazy
,通过lazy 和 Suspense 组件我们就可以实现异步组件,如果你使用的是 React v16.6 以上版本:
最简单的实现方法:
// codes from https://react.docschina.org import React, { lazy, Suspense } from 'react'; const OtherComponent = lazy(() => import('./OtherComponent')); function MyComponent() { return ( <Suspense fallback={<div>Loading...</div>}> <OtherComponent /> </Suspense> ); } 复制代码
从 React 中引入 lazy
方法和 Suspense
组件,然后用 lazy 方法处理我们的组件,lazy 会返回一个新的React 组件,我们可以直接在 Suspense 标签内使用,这样组件就会在匹配的时候才加载。
lazy 接受一个函数作为参数,函数内部使用 import()
方法异步加载组件,加载的结果返回。
Suspense 组件的 fallback
属性是必填属性,它接受一个组件,在内部的异步组件还未加载完成时显示,所以我们通常传递一个 Loading
组件给它,如果没有传递的话,就会报错。
所以在使用 React Router 4 的时候,我们可以这样写:
import React, { lazy, Suspense } from 'react'; import { HashRouter, Route, Switch } from 'react-router-dom'; const Index = lazy(() => import('components/Index')); const List = lazy(() => import('components/List')); class App extends React.Component { render() { return <div> <HashRouter> <Suspense fallback={Loading}> <Switch> <Route path="/index" exact component={Index}/> <Route path="/list" exact component={List}/> </Switch> </Suspense> </HashRouter> </div> } } function Loading() { return <div> Loading... </div> } export default App; 复制代码
在某些 React 版本中,lazy 函数还有 bug,会导致 React Router 的 component 属性接受 lazy 函数返回结果时报错: React.lazy makes Route's proptypes fail 。
我也遇到了这种 bug,具体的依赖版本如下:
"react": "^16.7.0", "react-dom": "^16.7.0", "react-router-dom": "^4.3.1" 复制代码
首次安装依赖后就再也没有更新过,所以小版本应该也是上面的小版本,不存在更新。
解决方法可以把 lazy 的结果放在函数的返回结果中:
import React, { lazy, Suspense } from 'react'; import { HashRouter, Route, Switch } from 'react-router-dom'; const Index = lazy(() => import('components/Index')); const List = lazy(() => import('components/List')); class App extends React.Component { render() { return <div> <HashRouter> <Suspense fallback={Loading}> <Switch> <Route path="/index" exact component={props => <Index {...props}/>}/> <Route path="/list" exact component={props => <List {...props}/>}/> </Switch> </Suspense> </HashRouter> </div> } } function Loading() { return <div> Loading... </div> } export default App; 复制代码
上面代码和之前唯一的不同就是把 lazy 返回的组件包裹在匿名函数中传递给 Route 组件的 component 属性。
这样我们的组件都会在路由匹配的时候才开始加载,Webpack 也会自动代码进行 code split,切割成很多小块,减小了首页的加载时间以及单独一个 js 文件的体积。在工作中已经实践过了,确实好用:
如果没有使用 React v16.6 以上版本,也可以自己实现,我们可以写一个专门用于异步加载的函数:
function asyncComponent(importComponent) { class AsyncComponent extends React.Component { render() { return this.state.component; } state = { component: null } async componentDidMount() { const { default: Component } = await importComponent(); this.setState({ component: <Component/> }); } } return AsyncComponent; } 复制代码
使用的方法与 React.lazy
相同,传入一个异步加载的函数即可,上面这个函数需要注意的地方就是 import()
进来的组件被包裹在 default 属性里,结构时要用 const { default: Component } = ...
这种形式。
效果如下:
总的来说:
import
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
TCP/IP网络管理
亨特 / 电子工业 / 2006年3月1日 / 79.00元
本书是一本架设与维护TCP/IP网络的完整指南,无论你是在职的系统管理员,还是需要访问Internet的家用系统用户,都可从本书获得帮助。本书还讨论了高级路由协议(RIPv2、OSPF、BGP),以及实现这些协议的gated软件。对于各种重要的网络服务,如DNS,Apache,sendmail,Samba,PPP和DHCP,本书都提供了配置范例,以及相关的软件包与工具的语法参考。一起来看看 《TCP/IP网络管理》 这本书的介绍吧!