ReactJS 教程

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 事件 ReactJS 状态管理 ReactJS 状态管理 API ReactJS 无状态组件 ReactJS Hooks 进行状态管理 ReactJS Hooks 的组件生命周期 ReactJS 布局组件 ReactJS 分页 ReactJS Material UI ReactJS Http 客户端编程 ReactJS 表单编程 ReactJS 受控组件 ReactJS 非受控组件 ReactJS Formik ReactJS 条件渲染 ReactJS 列表 ReactJS Key 键 ReactJS 路由 ReactJS Redux ReactJS 动画 ReactJS Bootstrap ReactJS Map ReactJS 表格 ReactJS 使用 Flux 管理状态 ReactJS 测试 ReactJS CLI 命令 ReactJS 构建和部署 ReactJS 示例

Hooks

ReactJS Hooks 简介 ReactJS 使用 useState ReactJS 使用 useEffect ReactJS 使用 useContext ReactJS 使用 useRef ReactJS 使用 useReducer ReactJS 使用 useCallback ReactJS 使用 useMemo ReactJS 自定义 Hooks

ReactJS 高级

ReactJS 可访问性 ReactJS 代码拆分 ReactJS 上下文 ReactJS 错误边界 ReactJS 转发 Refs ReactJS 片段 ReactJS 高阶组件 ReactJS 与其他库集成 ReactJS 优化性能 ReactJS Profiler API ReactJS Portals ReactJS 不使用 ES6 ECMAScript ReactJS 不使用 JSX 的 React ReactJS Reconciliation ReactJS Refs 和 DOM ReactJS 渲染道具 ReactJS 静态类型检查 ReactJS 严格模式 ReactJS Web 组件

其他概念

ReactJS 日期选择器 ReactJS Helmet ReactJS 内联样式 ReactJS PropTypes ReactJS BrowserRouter ReactJS DOM ReactJS 轮播 ReactJS 图标 ReactJS 表单组件 ReactJS 参考 API

ReactJS 有用资源

ReactJS 快速指南 ReactJS 备忘录 Axios 备忘录 ReactJS 有用资源 ReactJS 讨论


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 组件包含一个 fallback 属性来指定后备 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 应用程序并使用以下命令启动它。

create-react-app myapp
cd myapp
npm

接下来,打开 App.css (src/App.css) 并删除所有 CSS 类。

// 删除所有 css 类

接下来,创建一个简单的 hello 组件 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 属性来呈现具有给定名称的 hello 消息。

接下来,创建一个简单的组件 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() 加载 hello 组件,如下所示 −

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 组件来使用它。

最后,在浏览器中打开应用程序并检查最终结果。延迟加载在前端没有任何可见的变化。它将以通常的方式呈现 hello 组件,如下所示 −

应用延迟加载

摘要

代码拆分将有助于通过仅加载特定页面中使用的必要组件来优化大型应用程序。 Suspense 和错误边界组件可以用来处理动态加载组件时出现的意外错误。