一、使用react-loadable
-
其中用到:
loader: () => import('pages/home/index')
,运行会报错:
-
经过提示进行安装:
npm I -D @babel/plugin-syntax-dynamic-import
,然后需要在babel里配置此plugin来支持,否则还是会报错。
plugins: [
// 支持 () => import('./Home')语法
'@babel/plugin-syntax-dynamic-import',
]
- 再次运行,成功。
- 页面使用如下:
Loading组件的props有以下属性:
const Loading = (props) => {
// props为下面的值
}
Loading组件的props
import Loadable from 'react-loadable';
// 加载中过渡组件
const Loading = ({ pastDelay }) => {
if (pastDelay) { // 超过200ms则为true,没超过就为false
return <p>loading</p>; // 当页面请求超过200ms就会显示loading,让用户等待。
}
return null; // 当页面请求很快时,不超过200ms,则页面直接加载组件,即空白页面。
};
// 动态引入Home组件
const Home = Loadable({
loader: () => import('pages/home/index'),
loading: Loading,
delay: 200
});
const App = () => (
<Router history={historyInstance}>
<Switch>
<Route exact path='/' component={Home} />
</Switch>
</Router>
);
二、使用React.Suspense(使用 React 的核心库,替换第三方库)
- app.js代码初步实现
import React, { Suspense } from 'react'; // 将lazy直接写在{ lazy }里也可以
import { Router, Switch, Route } from 'react-router';
import { createBrowserHistory } from 'history';
import '@/app.less';
const historyInstance = createBrowserHistory();
const Home = React.lazy(() => import('pages/home/index'));
const App = () => (
<Router history={historyInstance}>
<Suspense fallback={<p>loading</p>}>
<Switch>
<Route exact path='/' component={Home} />
</Switch>
</Suspense>
</Router>
);
export default App;
- 特点:
(1)没有在内置支持 delay 功能,因此,即使加载工程只需要几毫秒的时间, fallback也会被执行;
(2)即:每个页面出来之前都会先加载loading组件;
三、添加Error Boundary
- 思想:当组件发生错误时,即抛出错误(throw error),会直接进入
static getDerivedStateFromError()
生命周期,从而显示Error Boundary组件相应的error UI。- 顺序:
页面组件出错
---static getDerivedStateFromError()
---componentDidCatch()
---错误callback UI
ErrorBoundary组件代码附上:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
class ErrorBoundary extends Component {
constructor() {
super();
this.state = {
errorStatus: false
};
}
static getDerivedStateFromError() {
// 接受一个参数error,和底下的didcatch的error一样
// throw new Error抛出会立马捕捉到,并处理
return {
errorStatus: true
};
}
componentDidCatch(error, info) {
// You can also log the error to an error reporting service
console.info(error, info);
}
render() {
const { errorStatus } = this.state;
const { children } = this.props;
if (errorStatus) {
return <div>error</div>;
}
return children;
}
}
ErrorBoundary.propTypes = {
children: PropTypes.shape({}).isRequired
};
export default ErrorBoundary;
App组件:
import React, { Suspense } from 'react';
import { Router, Switch, Route } from 'react-router';
import { createBrowserHistory } from 'history';
import { ErrorBoundary, Com1 } from 'components/index';
import '@/app.less';
const historyInstance = createBrowserHistory();
const Home = React.lazy(() => import('pages/home/index'));
const App = () => (
<Router history={historyInstance}>
<ErrorBoundary> /*错误边界组件*/
<Suspense fallback={<p>loading</p>}>
<Switch>
<Route exact path='/' component={Home} />
<Route path='/next' component={Com1} />
</Switch>
</Suspense>
</ErrorBoundary>
</Router>
);
export default App;
四、支持箭头函数语法
- 为了支持箭头函数的写法,并在函数里面使用组件类中的
this
,可以避免每次需要使用bind
将this
和函数绑定。基于此,需要新加插件,即:安装npm i -D @babel/plugin-proposal-class-properties
。
对比:
handleClick() {
// 拿不到this:undefined
}
render() {
return (
<div>
<Button type="primary" onClick={this.handleClick}>按钮</Button>
</div>
);
}
handleClick() {
// 可以拿到this
}
render() {
return (
<div>
<Button type="primary" onClick={this.handleClick.bind(this)}>按钮</Button>
</div>
);
}
handleClick = () => {
// 可以拿到this
}
render() {
return (
<div>
<Button type="primary" onClick={this.handleClick}>按钮</Button>
</div>
);
- 安装之后,并在
babel.config.js
里配置plugin,再次运行正常。
// plugins 在 presets 前执行
module.exports = {
// plugins 加载顺序,数组从前往后
plugins: [
'@babel/plugin-syntax-dynamic-import', // 支持 `() => import('./Home')` 语法
['@babel/plugin-proposal-class-properties', { loose: true }], // 支持 `handleChange = () => {}` 语法
['babel-plugin-import', { libraryName: 'antd', style: true }] // 按需加载 `antd` 组件, `style: true` 会加载 less 文件
],
// presets 加载顺序,数组从后往前
presets: ['@babel/react'],
};
五、 整理文件,添加router文件
将使用React.lazy
加载的页面都放在 router/index.js
文件下,统一配置,如:
import { lazy } from 'react';
const Home = lazy(() => import('pages/home/index'));
const routes = [
{
name: 'home',
path: '/',
component: Home
}
];
export default routes;
app.js就可以循环显示了,如:
import React, { Suspense } from 'react';
import { Router, Switch, Route } from 'react-router';
import { createBrowserHistory } from 'history';
import { ErrorBoundary, Loading } from 'components/index';
import '@/app.less';
import routes from 'router/index';
const historyInstance = createBrowserHistory();
const App = () => (
<Router history={historyInstance}>
<ErrorBoundary>
<Suspense fallback={<Loading />}>
<Switch>
{
routes.map(item => (
<Route exact key={item.path} path={item.path} component={item.component} />
))
}
</Switch>
</Suspense>
</ErrorBoundary>
</Router>
);
export default App;
以上,本部分完成。
网友评论