# 前言

single-spa-react 是一个辅助库,它可以帮助React应用程序实现 single-spa 需要的命周期函数(bootstrap、mount 和 unmount)。请查看 single-spa-react github (opens new window)

# 安装

npm install --save single-spa-react
# or
yarn add single-spa-react

另外,您也可以通过添加 <script src="https://unpkg.com/single-spa-react"> 并访问全局变量 singleSpaReact 来使用 single-spa-react

这里我更建议使用 npm init single-spa --framework react 脚手架安装,对于初学者来说会省很多事情

image-20210210171940641

安装完成后的提示在之前的章节有过讲解了,就不多做赘述了

项目的初始化的目录结构基本就是下图:

image-20210210171949684

# 项目结构

# 入口文件(spa-spa.js)

这里的名字是根据在安装过程中,通过 Organiztion nameProject name 组合而成的,上面安装的时候我就是随便起的名字就是 spa 和 spa,所以成的就是 spa-spa,名字是 O-P 的结构

import React from "react";
import ReactDOM from "react-dom";
import singleSpaReact from "single-spa-react";
import Root from "./root.component";

const lifecycles = singleSpaReact({
  React,
  ReactDOM,
  rootComponent: Root,
  errorBoundary(err, info, props) {
    // Customize the root error boundary for your microfrontend here.
    return null;
  },
});

export const { bootstrap, mount, unmount } = lifecycles;

最主要的是使用了 singleSpaReact 这个 react 的微应用库,用于创建一个微应用对象:

参数接收一个对象:

  • React (必填)
  • React DOM (必填)
  • rootComponent (必填) 将被渲染的顶层React组件。只有在提供了 loadRootComponent 的情况下才可以省略。
  • loadRootComponent:(可选) 一个加载函数。由 parcel 触发用来获取自定义 single-spa 属性 的loading 方法,返回值为 Promise。 如果如提供了此选项,它将取代 rootComponent 选项。它的目的是为了帮助那些想要懒加载根组件的源代码的人。源代码将在 bootstrap 生命周期中被懒加载。
  • suppressComponentDidCatchWarning:(可选) 一个布尔值,表示当 rootComponent 没有实现 componentDidCatch 时,single-spa-react 是否应该发出警告。默认值为 false
  • domElementGetter:(可选) 一个不接收任何参数并返回一个DOM元素的函数。这个 dom 元素是 React 应用程序将被初始、挂载和卸载的地方。注意,这个选项可以省略。当省略时, domElementGetterdomElement 的自定义 single-spa 属性会被使用。要使用这些,请执行 singleSpa.registerApplication(name, app, activityFn, {domElementGetter: function() {...}})singleSpa.registerApplication(name, app, activityFn, {domElement: document.getElementById(...)})。如果通过这些方法中的任何一个都找不到dom元素,那么就会创建一个容器div并附加到 document.body 中。
  • parcelCanUpdate:(可选) 一个布尔值,控制是否为返回的 parcel 创建更新生命周期。注意,该选项不影响单个spa应用,只影响 parcels。默认情况下,它是 true
  • renderType:(可选) 可选值:['render','hydrate','createRoot','createBlockingRoot']。 默认为 'render'。允许你选择你想在你的应用程序中使用哪个 ReactDOM 渲染方法。

返回的值也是一个对象,就是当前微应用的所有生命周期方法

export const { bootstrap, mount, unmount } = lifecycles;

# 业务代码入口(root.component.js)

该文件就是正常的 react 业务开发的代码了,没什么特殊的

# 公共路径(set-public-path.js)

这里其实是 systemjs 框架内,用于提供公共目录入口的文件

# 注意

对于react@>=16,最好的做法是让每个 single-spa 应用程序的根应用程序实现 componentDidCatch,以避免整个应用程序在发生错误时意外卸载。更多细节请参见reactjs.org/blog/2017/0… (opens new window)

# Parcels

single-spa-react 也可以用来创建一个 single-spa parcel(而不是 single-spa 应用程序)。要做到这一点,只需调用 singleSpaReact() ,就像调用应用程序一样,除了没有 domElementGetter 之外(因为这些都是由挂载 parcel 的代码提供的)。

此外,single-spa-react 提供了一个 <Parcel> 组件,使使用框架的人不需要知道 single-spa parcels。 这使得你可以把 parcel 放到你的 render 方法的jsx中,而不需要实现 componentDidMountcomponentWillUnmount。 你可以通过npm安装该库并导入 single-spa-react/parcel ,或者通过添加,然后用window.Parcel.default 访问 Parcel 组件。

# Parcel props

  • config (必填):要么是一个single-spa parcel配置对象,要么是一个 "加载函数",返回一个 resolve 包裹配置的 Promise
  • wrapWith (可选):tagName 字符串。 将创建一个该类型的 dom 节点,包裹 Parcel 生成的节点。 默认:div
  • appendTo (可选):将 parcel append 到此 dom 元素下。 默认情况下,这是不需要的,因为包裹将挂载在包裹组件所呈现的 DOM 中。 当想要把 parcel 放到 document.body 或 指定dom特定位置时很有用。
  • mountParcel (有时需要,有时不需要):由 single-spa 所提供的 mountParcel 功能。 我们建议使用应用程序的 mountParcel 函数, 而非 single-spamountParcel 函数. 这样,single-spa 可以跟踪父子关系,并在应用程序卸载时自动卸载应用程序的包。请注意,如果 <Parcel> 组件是由使用 single-spa-reactsingle-spa 应用程序 render 而来的,则无需传递prop,因为 <Parcel> 可以从 SingleSpaContext 中获取 prop。
  • handleError (可选):Function 类型。parcel 抛出错误时被调用。 如果没有提供,默认情况下,将在窗口上抛出错误。
  • parcelDidMount (可选):Function 类型。当包 parcel 完成装载时,将调用该命令。

例子:

function CustomDomFn() {
  return <div>123</div>
}
const CustomDom = singleSpaReact({
  React,
  ReactDOM,
  rootComponent: CustomDomFn
})
export default function Root(props) {
  console.log(CustomDom)

  return (
    <div>
      {props.name} i1s mounted!
      {/* <CustomDom /> */}
      <Parcel
        config={CustomDom}
      />
    </div>
  )
}
阅读全文