之前介绍过代码分割的插件react-loadable:react代码分割(一)之react-loadable,这次介绍一下react官方提供的方法
动态import语法
在react官网的代码分割部分阐述了为什么要代码分割,以及代码分割实现需要靠动态import进行
为了方便使用,react自身提供了lazy和suspense组合使用进行代码分割
使用样例
首先使用lazy引入组件
// router.ts
import { lazy } from "react"
const Home = lazy(() => import("../views/Home"));
const Login = lazy(() => import("../views/Login"));
const NotFound = lazy(() => import("../components/NotFound"));
export default [
{ path: "/", key: 1, name: "首页", component: Home, auth: true },
{ path: "/home", key: 2, name: "首页", component: Home, auth: true },
{ path: "/login", key: 2, name: "登录", component: Login },
{ path: "*", key: 3, name: "notfound", component: NotFound }
]
使用router管理页面
import React, { Suspense } from "react";
import { Switch, Route, Redirect, HashRouter } from "react-router-dom";
import Routers from "./router";
import { connect } from 'react-redux'
import MyErrorBoundary from "../components/ErrorBoundary"
import { loginState } from "@/store/reducer/loginReducer"
import Navbar from "@/components/Navbar";
import { LoadingOutlined } from "@ant-design/icons"
export interface routerProps {
login: loginState
}
const RouterView: React.FC<routerProps> = (props) => {
const _loginProps = props.login
return (<div style={{ width: "100%", height: "100%" }}>
<MyErrorBoundary>
<HashRouter>
{/* 导航跳转必须包裹在router中,不然组件无法使用useHistory和useLocation */}
<Navbar />
{/* fallback控制异步加载组件时等待的动画 */}
<Suspense fallback={< div style={{ width: "100%", height: "100%", fontSize: "50px", display: "flex", justifyContent: "center", alignItems: "center", color: "rgba(49, 213, 248, 1)" }}>
<LoadingOutlined />
</div>}>
<Switch>
{Routers.map((item) => {
const TempComponent = item.component;
// 根据组件是否需要权限验证以及登录状态控制页面显示
return <Route key={item.name} path={item.path} exact render={(props) =>
(!item.auth ? (<TempComponent {...props} />) : (_loginProps.status ? <TempComponent {...props} /> : <Redirect to={{
pathname: '/login',
state: { from: props.location }
}} />)
)} />
})}
</Switch>
</Suspense>
</HashRouter>
</MyErrorBoundary>
</div>)
}
const mapStateToProps = (state: any) => {
return {
login: state.login
}
}
export default connect(mapStateToProps)(RouterView);
Tips
1.与路由相关的组件如NavBar一定要放在Router下哦,不然获取不到路由相关的值
2.在路由管理界面也可以加上错误边界相关的组件,可以防止部分 UI 的 JavaScript 错误导致整个应用崩溃。
// ErrorBoundary.tsx
import React from "react";
import "./index.scss"
export default class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { error: null, errorInfo: null };
}
// static getDerivedStateFromError(error) {
// // 更新 state 使下一次渲染能够显示降级后的 UI
// return { hasError: true };
// }
componentDidCatch(error, errorInfo) {
// 你同样可以将错误日志上报给服务器
console.log(error, errorInfo);
this.setState({
error: error,
errorInfo: errorInfo
})
}
render() {
if (this.state.errorInfo) {
// 你可以自定义降级后的 UI 并渲染
return <div className="errorboundary">
<h2>页面错误</h2>
<details style={{ whiteSpace: 'pre-wrap' }}>
{this.state.error && this.state.error.toString()}
<br />
{this.state.errorInfo.componentStack}
</details>
</div>;
}
return this.props.children;
}
}