React知识点总结(六)

React知识点总结

文章目录

  • React知识点总结
  • 前言
  • React.lazy的基本原理
    • React.lazy的使用方法
    • React.Suspense大概原理
    • React.lazy的基本原理

前言

今天学习一下React懒加载的基本原理,React懒加载采用React.lazyReact.Suspense

React.lazy的基本原理

React.lazy的使用方法

import React, { Suspense } from 'react';

const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <OtherComponent />
      </Suspense>
    </div>
  );
}

React.lazy将原来的静态导入转换成了import(url)动态导入
import(url)返回的是一个Promise对象,其参考实现方式如下:

function import(url) {
  return new Promise((resolve, reject) => {
    const script = document.createElement("script");
    const tempGlobal = "__tempModuleLoadingVariable" + Math.random().toString(32).substring(2);
    script.type = "module";
    script.textContent = `import * as m from "${url}"; window.${tempGlobal} = m;`;

    script.onload = () => {
      resolve(window[tempGlobal]);
      delete window[tempGlobal];
      script.remove();
    };

    script.onerror = () => {
      reject(new Error("Failed to load module script with URL " + url));
      delete window[tempGlobal];
      script.remove();
    };

    document.documentElement.appendChild(script);
  });
}

React.Suspense大概原理

React.Suspense会捕获子组件抛出的异常,如果抛出的异常的内容是Promise,且状态为pending,则会展示fallback的内容,若状态为resolved,则会展示动态导入的组件。

React.lazy的基本原理

React.lazy函数返回一个LazyComponent类型的对象:

export function lazy<T, R>(ctor: () => Thenable<T, R>): LazyComponent<T> {
  let lazyType = {
    ?typeof: REACT_LAZY_TYPE,
    _ctor: ctor,
    // React uses these fields to store the result.
    _status: -1,
    _result: null,
  };

  return lazyType;
}

该对象保存着ctor函数,状态以及动态导入的结果。
在对LazyComponent对象的解析过程中,主要是调用了readLazyComponentType函数:

// Pending = 0, Resolved = 1, Rejected = 2
export function readLazyComponentType<T>(lazyComponent: LazyComponent<T>): T {
  const status = lazyComponent._status;
  const result = lazyComponent._result;
  switch (status) {
    case Resolved: {
      const Component: T = result;
      return Component;
    }
    case Rejected: {
      const error: mixed = result;
      throw error;
    }
    case Pending: {
      const thenable: Thenable<T, mixed> = result;
      throw thenable;
    }
    default: { // lazyComponent 首次被渲染
      lazyComponent._status = Pending;
      const ctor = lazyComponent._ctor;
      const thenable = ctor();
      thenable.then(
        moduleObject => {
          if (lazyComponent._status === Pending) {
            const defaultExport = moduleObject.default;
            lazyComponent._status = Resolved;
            lazyComponent._result = defaultExport;
          }
        },
        error => {
          if (lazyComponent._status === Pending) {
            lazyComponent._status = Rejected;
            lazyComponent._result = error;
          }
        },
      );
      // Handle synchronous thenables.
      switch (lazyComponent._status) {
        case Resolved:
          return lazyComponent._result;
        case Rejected:
          throw lazyComponent._result;
      }
      lazyComponent._result = thenable;
      throw thenable;
    }
  }
}

从中可以看出,初始的LazyComponent对象状态为-1,会执行default情况,并抛出一个pending状态的Promise。当该Promise的状态变为resolved时,会将动态导入的组件赋值给LazyComponent对象的result,最终将组件返回。

参考博文:
[1] 深入理解React:懒加载(lazy)实现原理
[2] [译] React 16.6 懒加载(与预加载)组件

你可能感兴趣的:(React知识点总结(六))