- ReactJS 菜鸟教程
- ReactJS 教程
- ReactJS - 简介
- ReactJS - 安装
- ReactJS - 特性
- ReactJS - 优点和缺点
- ReactJS - 架构
- ReactJS - 创建 React 应用程序
- ReactJS - JSX
- ReactJS - 组件
- ReactJS - 嵌套组件
- ReactJS - 使用组件
- ReactJS - 组件集合
- ReactJS - 样式
- ReactJS - 属性(props)
- ReactJS - 使用属性创建组件
- ReactJS - props 验证
- ReactJS - 构造函数
- ReactJS - 组件生命周期
- ReactJS - 事件管理
- ReactJS - 创建事件感知组件
- ReactJS - 在Expense Manager APP中引入事件
- ReactJS - 状态管理
- ReactJS - 状态管理 API
- ReactJS - 无状态组件
- ReactJS - 使用 React Hooks 进行状态管理
- ReactJS - 使用 React 钩子的组件生命周期
- ReactJS - 组件的布局
- ReactJS - 分页
- ReactJS - Material 用户界面
- ReactJS - Http 客户端编程
- ReactJS - 表单编程
- ReactJS - 受控组件
- ReactJS - 不受控制的组件
- ReactJS - Formik
- ReactJS - 条件渲染
- ReactJS - 列表
- ReactJS - 键
- ReactJS - 路由
- ReactJS - 冗余
- ReactJS - 动画
- ReactJS - 引导程序
- ReactJS - 地图
- ReactJS - 表格
- ReactJS - 使用 Flux 管理状态
- ReactJS - 测试
- ReactJS - CLI 命令
- ReactJS - 构建和部署
- ReactJS - 示例
- ReactJS - 钩子简介
- ReactJS - 使用 useState
- ReactJS - 使用 useEffect
- ReactJS - 使用 useContext
- ReactJS - 使用 useRef
- ReactJS - 使用 useReducer
- ReactJS - 使用 useCallback
- ReactJS - 使用 useMemo
- ReactJS - 自定义钩子
- ReactJS - 可访问性
- ReactJS - 代码拆分
- ReactJS - 上下文
- ReactJS - 错误边界
- ReactJS - 转发引用
- ReactJS - 片段
- ReactJS - 高阶组件
- ReactJS - 与其他库集成
- ReactJS - 优化性能
- ReactJS - 分析器 API
- ReactJS - 门户
- ReactJS - 没有 ES6 ECMAScript 的 React
- ReactJS - 没有 JSX 的 React
- ReactJS - 协调
- ReactJS - 引用和 DOM
- ReactJS - 渲染属性
- ReactJS - 静态类型检查
- ReactJS - 严格模式
- ReactJS - Web 组件
- ReactJS - 日期选择器
- ReactJS - Helmet
- ReactJS - 内联样式
- ReactJS - 属性类型
- ReactJS - 浏览器路由器
- ReactJS - DOM
- ReactJS - 旋转木马
- ReactJS - 图标
- ReactJS - 表单组件
- ReactJS - 参考 API
ReactJS - 代码拆分
捆绑是前端应用程序的重要阶段之一。它将所有前端代码和依赖项捆绑到一个大包 (bundle.js) 中。最终的捆绑包由捆绑器优化大小。一些流行的打包器是 webpack、parcel 和 rollup。在大多数情况下,最终的捆绑包会很好。如果最终捆绑的代码很大,则可以指示打包器将代码捆绑到多个项目中,而不是单个大块。
让我们学习如何提示打包器拆分代码并将其单独捆绑。
动态导入
动态导入指示打包器拆分代码。动态导入基本上是根据需要获取所需的模块。执行正常操作的代码如下图所示 -
import { round } from './math';
console.log(round(67.78));
可以动态导入相同的代码,如下所示 -
import("./math").then(math => {
console.log(math.round(67.78);
});
React Lazy 组件
React 提供了一个函数 React.lazy 来动态导入组件。通常,正如我们所知,将导入一个 react 组件,如下所示 -
import MyComponent from './MyComponent';
使用 React.lazy() 函数动态导入上述组件如下图 -
const MyComponent = React.lazy(() => import('./MyComponent'));
The imported component should be wrapped into a Suspense component to use it in the application.
import React, { Suspense } from 'react';
const MyComponent = React.lazy(() => import('./MyComponent'));
function App() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<MyComponent />
</Suspense>
</div>
);
}
Suspense 组件用于在加载原始组件的过程中加载临时 UI。Suspense 组件包含一个回退 props 来指定回退 UI。回退 UI 可以是任何 React 元素。有时,由于网络问题或代码错误,动态组件可能无法加载。我们可以使用误差边界来处理这些情况,如下所示 -
import React, { Suspense } from 'react';
import MyErrorBoundary from './MyErrorBoundary';
const MyComponent = React.lazy(() => import('./MyComponent'));
const AnotherComponent = () => (
<div>
<MyErrorBoundary>
<Suspense fallback={<div>Loading...</div>}>
<section>
<MyComponent />
</section>
</Suspense>
</MyErrorBoundary>
</div>
);
这里
- MyErrorBoundary 包裹在 Suspense 组件周围。
- 如果加载 MyComponent 时出现任何错误,则 MyErrorBoundary 将处理错误并回退到其组件中指定的通用 UI。
应用代码拆分的最佳方案之一是路由。路由可用于应用代码拆分,如下所示 -
import React, { Suspense, lazy } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));
const App = () => (
<BrowserRouter>
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</Suspense>
</BrowserRouter>
);
这里
- 所有路由(组件)都使用 React.lazy() 功能加载
- 由于所有路由(Home 和 About )都是通过动态导入加载的,因此每个路由在其初始化过程中将仅加载必要的组件,而不是所有组件。
React.lazy() 仅支持默认导出。在 React 中,我们可以通过指定动态名称而不是默认关键字来导出组件,如下所示 -
export const MyComponent = /* ... */;
为了使其在 React.lazy() 中可用,我们可以使用 default 关键字重新导出组件,如下所示 -
export { MyLazyComponent as default } from "./MyComponent.js";
然后,我们可以像往常一样导入它,
import React, { lazy } from 'react';
const MyComponent = lazy(() => import("./MyComponent.js"));
应用延迟加载
让我们创建一个新的 react 应用程序,在本节中学习如何应用代码拆分。
首先,创建一个新的 react 应用程序并使用以下命令启动它。
cd myapp
npm
接下来,打开 App.css (src/App.css) 并删除所有 CSS 类。
// remove all css classes
接下来,创建一个简单的你好组件 Hello (src/Components/Hello.js) 并呈现一条简单的消息,如下所示 -
import React from "react";
class Hello extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<div>Hello, {this.props.name}</div>
);
}
}
export default Hello;
在这里,我们使用了 name 属性来渲染具有给定名称的你好消息。
接下来,创建一个简单的组件 SimpleErrorBoundary (src/Components/SimpleErrorBoundary.js) 并在出错时渲染回退 UI 或子组件,如下所示 -
import React from "react";
class SimpleErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
console.log(error);
console.log(errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>Please contact the administrator.</h1>;
}
return this.props.children;
}
}
export default SimpleErrorBoundary;
这里
- hasError 是用 false 值初始化的状态变量。
- getDerivedStateFromError 在出现错误时更新错误状态。
- componentDidCatch 将错误记录到控制台中。
- render 将根据应用程序中的错误呈现错误的 UI 或子项。
接下来,打开 App 组件(src/App.js),并通过 React.lazy() 加载 你好 组件,如下图所示 -
import './App.css'
import React, { Suspense, lazy } from 'react';
import SimpleErrorBoundary from './Components/SimpleErrorBoundary';
const Hello = lazy(() => import('./Components/Hello'));
function App() {
return (
<div className="container">
<div style={{ padding: "10px" }}>
<div>
<SimpleErrorBoundary>
<Suspense fallback="<div>loading...</div>">
<Hello name="Peter" />
</Suspense>
</SimpleErrorBoundary>
</div>
</div>
</div>
);
}
export default App;
在这里,我们有,
- 从 react 包中导入了 lazy 和 Suspense 组件。
- 通过使用 Suspense 和 SimpleErrorBoundary 组件包装它来使用 Hello 组件。
最后,在浏览器中打开应用程序并检查最终结果。延迟负载在前端没有任何可见的变化。它将以通常的方式呈现你好组件,如下所示 -
总结
代码吐槽将有助于优化大型应用程序,只需加载特定页面中使用的必要组件。Suspense and error boundary component 可用于在动态加载组件时处理意外错误。