美文网首页
React 代码分割&错误边界(6)

React 代码分割&错误边界(6)

作者: 示十 | 来源:发表于2022-09-25 16:18 被阅读0次

    代码分割

    import 静动态导入

    • 静态导入:static import import xxx from 'xxx'
      导入并加载时,导入的模块会被编译,不是按需编译
    • 动态导入:dynamic import import('xxx')
      根据条件或按需的模块导入

    动态导入应用场景:

    1. 模块太大了,使用可能性很低的模块是存在的,这些模块不需要马上加载
    2. 模块的导入占用大量的系统内存
    3. 模块需要异步获取
    4. 导入模块时,需要动态构建路径 import('./' + a + b + '.js') // 动态说明符(静态导入只支持静态说明符:'./a/b/c.js'
    5. 模块中的代码需要程序触发了某些条件才运行

    不要滥用动态导入,静态导入是有利于初始化依赖,静态的程序分析和 tree sharking 静态导入会使其更好的工作

    babel 解析 import() 依赖 @babel/plugin-syntax-dynamic-import

    // index.module
    export default class Test{
      constructor(){
        console.log('new Test');
      }
    }
    
    // 动态导入返回一个 promise,res 接收模块的默认导出
    import("./index.module").then((res) => {
      console.log(res);
      new res.default();
    });
    

    lazy 内置方法 / Suspense React 内置组件

    lazyReact 提供的懒(动态)加载组件的方法 React.lazy(函数:动态导入组件),该函数返回一个 Promise

    减少打包体积,对初次渲染不适用的组件延迟加载

    依赖内置组件 Suspense,给 lazy 加上 loading 指示器的一个容器组件

    // ./lazy/Loading.jsx
    export default class Loading extends React.Component {
      render() {
        return <div>Loading...</div>;
      }
    }
    
    // ./lazy/Main.jsx
    export default class Main extends React.Component {
      render() {
        return <div>Main</div>;
      }
    }
    
    // index.jsx
    // lazy 接收一个动态导入组件的函数
    // 该函数返回一个 promise
    // promise 会 resolve 一个默认导出(export default)的 React 组件
    // Suspense 只和 lazy 配合实现组件等待加载指示器的功能
    
    import Loading from "./lazy/Loading";
    const MainComponent = React.lazy(() => import("./lazy/Main"));
    
    class App extends React.Component {
      render() {
        return (
          <React.Suspense fallback={Loading}>
            <MainComponent />
          </React.Suspense>
        );
      }
    }
    ReactDOM.render(<App />, document.querySelector("#app"));
    

    yarn add react-router react-router-dom -D

    错误边界

    React 16 增加的组件

    1. 防止某个组件的 UI 渲染错误导致整个应用崩溃
    2. 子组件发生 js 错误,有备用的渲染 UI
    3. 错误边界其实是一个组件,只能用 class 来写

    getDerivedStateFromError(error)

    参数:子组件抛出的错误

    返回新的 state

    作用:获取捕获的错误,修改错误装填

    渲染阶段调用,不允许出现副作用:setTimeoutrequestAnimationFrame

    错误边界组件捕获错误的时机:渲染时、生命周期函数中、组件树的构造函数中

    错误边界组件可以嵌套使用,且有冒泡机制,捕获的错误会一直往上抛,也就是说,里面的错误边界组件报错了,外层的错误组件可以捕获到

    无法捕获的场景:

    1. 事件处理函数内部错误
    2. 异步代码 setTimeoutajaxrequestAnimationFrame
    3. 服务端渲染(因为触发更新只能在客户端进行,不能在serve端进行)
    4. 错误边界组件内部错误

    componentDidCatch

    原型上的方法,componentDidCatch(error, info)
    参数:

    • error:抛出的错误
    • 组件引发错误相关的信息,组件栈

    作用:错误信息获取,运行副作用

    边界错误组件捕获异常,并进行后续处理

    在该组件抛出错误后调用

    class ErrorBoundary extends React.Component {
      state = {
        hasError: false,
      };
      static getDerivedStateFromError(error) {
        console.log(1);
        return { hasError: true };
      }
    
      componentDidCatch(error, info) {
        console.log(2);
        console.log(otherParams);
        console.log(error, info);
      }
    
      render() {
        if (this.state.hasError) {
          return <h1>hasError</h1>;
        }
        return this.props.children;
      }
    }
    
    class MyError extends React.Component {
      state = {
        hasError: false,
      };
      static getDerivedStateFromError(error) {
        return { hasError: true };
      }
    
      componentDidCatch(error, info) {
        console.log(error, info);
      }
    
      render() {
        if (this.state.hasError) {
          return <h1>My-Error</h1>;
        }
        return this.props.children;
      }
    }
    
    class Test extends React.Component {
      render() {
        // const data = {
        //   title: 9999,
        // };
        return <div>{data.title}</div>;
      }
    }
    class Sub extends React.Component {
      render() {
        return <div>sub content</div>;
      }
    }
    
    class App extends React.Component {
      render() {
        return (
          <div>
            <MyError>
              <ErrorBoundary>
                <Test />
              </ErrorBoundary>
            </MyError>
            <Sub />
          </div>
        );
      }
    }
    
    ReactDOM.render(<App />, document.querySelector("#app"));
    

    相关文章

      网友评论

          本文标题:React 代码分割&错误边界(6)

          本文链接:https://www.haomeiwen.com/subject/nxunortx.html