React 代碼分割&錯(cuò)誤邊界(6)

代碼分割

import 靜動(dòng)態(tài)導(dǎo)入

  • 靜態(tài)導(dǎo)入:static import import xxx from 'xxx'
    導(dǎo)入并加載時(shí),導(dǎo)入的模塊會(huì)被編譯,不是按需編譯
  • 動(dòng)態(tài)導(dǎo)入:dynamic import import('xxx')
    根據(jù)條件或按需的模塊導(dǎo)入

動(dòng)態(tài)導(dǎo)入應(yīng)用場(chǎng)景:

  1. 模塊太大了,使用可能性很低的模塊是存在的,這些模塊不需要馬上加載
  2. 模塊的導(dǎo)入占用大量的系統(tǒng)內(nèi)存
  3. 模塊需要異步獲取
  4. 導(dǎo)入模塊時(shí),需要?jiǎng)討B(tài)構(gòu)建路徑 import('./' + a + b + '.js') // 動(dòng)態(tài)說(shuō)明符(靜態(tài)導(dǎo)入只支持靜態(tài)說(shuō)明符:'./a/b/c.js'
  5. 模塊中的代碼需要程序觸發(fā)了某些條件才運(yùn)行

不要濫用動(dòng)態(tài)導(dǎo)入,靜態(tài)導(dǎo)入是有利于初始化依賴,靜態(tài)的程序分析和 tree sharking 靜態(tài)導(dǎo)入會(huì)使其更好的工作

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

// index.module
export default class Test{
  constructor(){
    console.log('new Test');
  }
}

// 動(dòng)態(tài)導(dǎo)入返回一個(gè) promise,res 接收模塊的默認(rèn)導(dǎo)出
import("./index.module").then((res) => {
  console.log(res);
  new res.default();
});

lazy 內(nèi)置方法 / Suspense React 內(nèi)置組件

lazyReact 提供的懶(動(dòng)態(tài))加載組件的方法 React.lazy(函數(shù):動(dòng)態(tài)導(dǎo)入組件),該函數(shù)返回一個(gè) Promise

減少打包體積,對(duì)初次渲染不適用的組件延遲加載

依賴內(nèi)置組件 Suspense,給 lazy 加上 loading 指示器的一個(gè)容器組件

// ./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 接收一個(gè)動(dòng)態(tài)導(dǎo)入組件的函數(shù)
// 該函數(shù)返回一個(gè) promise
// promise 會(huì) resolve 一個(gè)默認(rèn)導(dǎo)出(export default)的 React 組件
// Suspense 只和 lazy 配合實(shí)現(xiàn)組件等待加載指示器的功能

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

錯(cuò)誤邊界

React 16 增加的組件

  1. 防止某個(gè)組件的 UI 渲染錯(cuò)誤導(dǎo)致整個(gè)應(yīng)用崩潰
  2. 子組件發(fā)生 js 錯(cuò)誤,有備用的渲染 UI
  3. 錯(cuò)誤邊界其實(shí)是一個(gè)組件,只能用 class 來(lái)寫(xiě)

getDerivedStateFromError(error)

參數(shù):子組件拋出的錯(cuò)誤

返回新的 state

作用:獲取捕獲的錯(cuò)誤,修改錯(cuò)誤裝填

渲染階段調(diào)用,不允許出現(xiàn)副作用:setTimeout、requestAnimationFrame

錯(cuò)誤邊界組件捕獲錯(cuò)誤的時(shí)機(jī):渲染時(shí)、生命周期函數(shù)中、組件樹(shù)的構(gòu)造函數(shù)中

錯(cuò)誤邊界組件可以嵌套使用,且有冒泡機(jī)制,捕獲的錯(cuò)誤會(huì)一直往上拋,也就是說(shuō),里面的錯(cuò)誤邊界組件報(bào)錯(cuò)了,外層的錯(cuò)誤組件可以捕獲到

無(wú)法捕獲的場(chǎng)景:

  1. 事件處理函數(shù)內(nèi)部錯(cuò)誤
  2. 異步代碼 setTimeout、ajaxrequestAnimationFrame
  3. 服務(wù)端渲染(因?yàn)橛|發(fā)更新只能在客戶端進(jìn)行,不能在serve端進(jìn)行)
  4. 錯(cuò)誤邊界組件內(nèi)部錯(cuò)誤

componentDidCatch

原型上的方法,componentDidCatch(error, info)
參數(shù):

  • error:拋出的錯(cuò)誤
  • 組件引發(fā)錯(cuò)誤相關(guān)的信息,組件棧

作用:錯(cuò)誤信息獲取,運(yùn)行副作用

邊界錯(cuò)誤組件捕獲異常,并進(jìn)行后續(xù)處理

在該組件拋出錯(cuò)誤后調(diào)用

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"));
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容