ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

在 Vue 主应用中声明式接入微应用:qiankun `<MicroApp>` 组件与 `MicroAppLink` 完整指南

在 Vue 主应用中声明式接入微应用:qiankun `<MicroApp>` 组件与 `MicroAppLink` 完整指南 在 Vue 主应用中声明式接入微应用qiankunMicroApp组件与MicroAppLink完整指南【免费下载链接】qiankun Blazing fast, simple and complete solution for micro frontends.项目地址: https://gitcode.com/gh_mirrors/qi/qiankunqiankunjs/vue是 qiankun 官方提供的 Vue 绑定包通过MicroApp组件以声明式方式加载、挂载、更新与卸载微应用将微应用实例的生命周期与 Vue 组件的生命周期绑定在一起同时提供MicroAppLink用于 Vue 3 主应用的路由导航。本文以 docs/zh-CN/ecosystem/vue.md 为骨架结合仓库内 Vue 绑定源码 与 共享逻辑完整讲解安装方式、全部 Props 与插槽、加载/错误界面、props 深度更新、实例句柄与 CSS 钩子帮助你用最少的样板代码把微应用嵌入 Vue 主应用并理解组件底层与loadMicroApp的封装关系。安装npm install qiankunjs/vuerc qiankunrc主应用必须安装vue版本范围为^2.0.0 || 3.0.0。组件基于vue-demi构建同一份构建产物同时支持 Vue 2 和 Vue 3因此Vue 2 项目还需要额外安装vue/composition-api组件通过vue-demi使用组合式 API。从 packages/ui-bindings/vue/package.json 可以看到完整的依赖声明vue-demi^0.14.10作为运行时依赖负责 Vue 2/3 运行时切换vue与qiankun^3.0.0-rc.15作为 peer dependencyvue/composition-api^1.7.2标记为可选 peer dependency仅在 Vue 2 下需要。包同时提供 CJS 与 ESM 两种构建产物main指向dist/cjs、module指向dist/esm类型声明随dist/esm/index.d.ts一起发布。::: tip 使用前提MicroApp组件内部直接调用loadMicroApp单独使用时无需调用registerMicroApps或start。如果同一主应用里还使用基于路由的注册方式则仍需调用start。挂载和更新操作与 single-spa 生命周期的对应关系参见微应用生命周期与 props。 :::路由导航MicroAppLinkMicroAppLink用于 Vue 3 主应用的registerMicroApps路由模式。主应用完成注册并调用start后点击链接即可通过 single-spa 的navigateToUrl切换 URL由已注册的activeRule决定微应用的挂载与卸载。链接本身不加载微应用它只是路由导航的声明式入口。script setup langts import { MicroAppLink, type MicroAppLinkProps } from qiankunjs/vue; const appLink: MicroAppLinkProps { to: /app1, className: nav-link, activeClassName: is-active, }; /script template nav MicroAppLink v-bindappLink应用一/MicroAppLink MicroAppLink to/app2/settings replace应用二设置/MicroAppLink /nav /templateMicroAppLink 属性属性类型说明tostring必填。目标 URL作为链接的href。replaceboolean是否替换当前历史记录。默认值为false导航时新增一条历史记录。classNamestring链接的 CSS 类名模板中也可写为class-name。activeClassNamestring当前地址匹配目标地址前缀时追加的 CSS 类名模板中也可写为active-class-name。默认不追加。默认插槽提供链接内容。MicroAppLinkProps从包入口导出见 packages/ui-bindings/vue/src/index.ts。除组件自身使用的属性外class、target、rel、download、aria-*、data-*和事件监听器等原生链接属性都会传递给ahref由to指定。点击拦截与导航规则从源码 packages/ui-bindings/vue/src/MicroAppLink.ts 可以看到组件的onClick会先执行传入的click监听器再判断是否接管导航。其核心判断逻辑位于共享模块 packages/ui-bindings/shared/src/link.ts 的navigateMicroAppLink函数只有同时满足以下条件的左键点击才会阻止默认行为并在当前页面内导航事件未被preventDefault()取消未按下 Ctrl / Meta / Shift / Alt 修饰键目标为当前窗口有效的target为空或为_self未设置时遵循页面的base target设置链接为同源的 HTTP(S) 链接且不带download属性。外链、下载链接、其他窗口目标及带修饰键的点击均保留浏览器行为。可通过click.prevent取消组件导航。replace为true时组件使用history.replaceState替换当前记录并通过popstate事件通知路由监听器源码中用一个临时的事件监听对象探测 single-spa 是否已同步处理该通知避免重复派发popstate。activeClassName 的前缀匹配activeClassName的匹配逻辑在isMicroAppLinkActive函数中实现将目标 URL 解析后以它的pathname search hash为前缀匹配当前地址的对应部分。例如to/app1会匹配/app1/settings也会匹配/app10to/会匹配所有路径查询参数和哈希若包含在to中也参与前缀匹配。这是字符串前缀匹配不解析路由参数需要精确匹配时可由主应用自行设置className和aria-current。此外组件在挂载时会通过subscribeToMicroAppLinkLocation订阅popstate、hashchange和single-spa:routing-event事件确保浏览器前进后退或 single-spa 重路由后activeClassName依然保持最新。基本用法script setup import { MicroApp } from qiankunjs/vue; /script template micro-app nameapp1 entryhttp://localhost:8000 / /templatename和entry是仅有的两个必填 prop。name用于标识当前实例entry用于指定微应用的 HTML 入口 URL。缺少其中任意一项时组件仅输出错误日志共享逻辑mountMicroApp中的the name and entry of MicroApp is needed不会加载微应用也不会抛出异常。组件会渲染一个class为qiankun-micro-app-container的div并将微应用内容流式写入该容器。只有启用加载状态或错误边界时组件才会额外渲染一层包裹元素详见下文加载与错误界面。从 MicroApp.ts 的render函数可以确认一个实现细节挂载容器div会先于插槽渲染。这是有意的设计——qiankun 以容器的 XPath 作为 Parcel 缓存键如果加载指示器条件渲染导致容器在 DOM 树中的兄弟序号变化会把同一个微应用拆散到两个缓存键下。PropsProp类型默认值说明namestring—必填。微应用实例的名称值发生变化时会重新挂载。entrystring—必填。微应用的 HTML 入口 URL。settingsAppConfiguration{ sandbox: true }传递给loadMicroApp的加载器和沙箱配置。参见 AppConfiguration。lifeCyclesLifeCyclesundefined由主应用提供的生命周期钩子包括beforeLoad、beforeMount、afterMount、beforeUnmount和afterUnmount。每项可传入函数或函数数组。参见生命周期钩子。autoSetLoadingbooleanfalse微应用加载期间渲染内置的加载指示器。autoCaptureErrorbooleanfalse加载失败时渲染内置的错误边界。wrapperClassNamestringundefined包裹元素上的额外 CSS 类名。仅在启用加载状态或错误边界时生效。classNamestringundefined挂载容器元素上的额外 CSS 类名。appPropsobjectundefined传递给微应用的 props。Vue 绑定仅通过该属性向微应用传递数据。::: infosettings的默认值与 React 绑定不同 Vue 绑定的settings默认值为{ sandbox: true }React 绑定则不设置默认值不会替你填任何默认项。两者的sandbox在 qiankun 核心运行时中默认值都为true因此不额外传值时行为一致。 :::::: warning 业务数据通过appProps传递 React 绑定会将MicroApp上的附加 prop 传递给微应用Vue 绑定则不会传递任意附加属性。业务数据必须放入appProps对象未声明的其他属性会被忽略。当前实现还会将autoSetLoading、autoCaptureError和appProps对象本身传入微应用业务代码不应依赖这些组件控制字段。 :::settings、lifeCycles等组件自身消费的属性在共享层被统一定义在componentOwnedProps列表中见 packages/ui-bindings/shared/src/index.tsomitSharedProps会把这些字段从最终传给微应用的 props 中剔除避免加载指示器插槽等渲染闭包泄漏进子应用。settingsAppConfigurationsettings与loadMicroApp的第二个参数结构相同。完整定义参见 AppConfiguration字段为fetch、streamTransformer、nodeTransformer和sandbox默认值为true。样式隔离、额外全局变量、孵化上下文和隔离插件均位于sandbox对象内部。template micro-app nameapp1 entryhttp://localhost:8000 :settings{ sandbox: { styleIsolation: true } } / /template如需为特定微应用关闭 JavaScript 沙箱可传入:settings{ sandbox: false }。相关行为参见 JavaScript 隔离和样式隔离。在共享层 mountMicroApp 的实现中settings会原样合并进loadMicroApp的configuration参数lifeCycles则作为第三个参数直接透传——源码注释特别指出历史上曾用concat(undefined, hook)包装每个钩子结果 qiankun 把[undefined, hook]当作钩子调用导致所有传入lifeCycles的应用挂载即失败因此现在改为原样透传。向微应用传递 propsappProps需要传递给微应用的数据应放入appPropsscript setup import { reactive } from vue; import { MicroApp } from qiankunjs/vue; const appProps reactive({ userId: 42, theme: dark }); /script template micro-app nameapp1 entryhttp://localhost:8000 :appPropsappProps / /template这些数据会作为props参数传给微应用导出的生命周期函数// 微应用内部 export async function mount(props) { console.log(props.userId); // 42 }组件会深度侦听appProps源码中watch(appProps, ..., { deep: true })。修改嵌套值例如appProps.theme light会尝试更新当前实例。执行更新前微应用必须导出update生命周期、处于MOUNTED状态并且尚未开始卸载。相关说明参见应用间共享状态与通信。::: tipupdate仅在挂载完成后执行 共享层updateMicroApp会等待mountPromise完成再按顺序处理更新并且仅在 Parcel 状态为MOUNTED时调用update。挂载期间发生的中间状态变化不保证逐次触发更新。 :::更新队列与防抖提示源码层面updateMicroApp通过_updatingPromise把每次更新串成一条链保证后一个更新必须等待前一个更新完成与组件状态变更顺序一致。首次更新以mountPromise为链的起点——注释明确指出这里只能补上起点而不能跳过本次更新否则宿主传入的第一次 props 变更会被直接吞掉。另外在开发环境下NODE_ENV development如果同一微应用在200ms 内更新次数过多updateMicroApp会打印一条优化提示警告[qiankunjs/ui-shared] It seems like microApp app1 is updating too many times in a short time(200ms)...这通常意味着主应用在频繁的响应式重渲染中反复改动了appProps值得检查是否需要节流或解耦数据更新频率。加载与错误界面加载指示器和错误边界均需显式启用。如果未启用这两项功能也未提供对应插槽组件只渲染挂载容器div。如果设置了autoSetLoading、autoCaptureError、#loader插槽或#error-boundary插槽中的任意一项组件会额外渲染class为qiankun-micro-app-wrapper的包裹元素用于容纳加载节点、错误节点和挂载容器。对应源码中mountMicroApp在开始加载时调用setLoading(true)在mountPromise成功或loadPromise/bootstrapPromise任一失败时调用setLoading(false)错误则通过setError交给组件的setComponentError统一处理。自动加载与错误捕获通过以下两个布尔 prop 启用内置指示器script setup import { MicroApp } from qiankunjs/vue; /script template micro-app nameapp1 entryhttp://localhost:8000 autoSetLoading autoCaptureError / /template内置界面仅提供基础占位内容默认加载界面MicroAppLoader.ts渲染文本loading...默认错误边界ErrorBoundary.ts渲染包含error.message的div。生产环境通常应使用下文介绍的插槽提供自定义界面。::: info 加载状态的初始值 Vue 绑定将loading初始化为falseReact 绑定的初始值则为true。微应用开始加载时该状态会设为true启用autoSetLoading后组件会在mountPromise完成时将其恢复为false。未启用autoSetLoading时组件不会渲染内置加载界面。 :::自定义loader插槽可通过#loader作用域插槽渲染自定义加载指示器。组件会将布尔值loading直接传给插槽加载期间为true加载结束后为false。script setup import CustomLoader from /components/CustomLoader.vue; import { MicroApp } from qiankunjs/vue; /script template micro-app nameapp1 entryhttp://localhost:8000 autoSetLoading template #loaderloading custom-loader :loadingloading / /template /micro-app /template#loader插槽的优先级高于内置加载界面。提供该插槽后组件不会渲染默认加载界面仍需设置autoSetLoading组件才会在mountPromise完成后自动将loading设为false。自定义错误边界插槽可通过#error-boundary作用域插槽渲染自定义错误界面。组件会将Error实例直接传给插槽。该插槽仅在发生错误后渲染。script setup import CustomErrorBoundary from /components/CustomErrorBoundary.vue; import { MicroApp } from qiankunjs/vue; /script template micro-app nameapp1 entryhttp://localhost:8000 template #error-boundaryerror custom-error-boundary :errorerror / /template /micro-app /template未捕获的错误会重新抛出如果既未启用autoCaptureError也未提供#error-boundary插槽则load、bootstrap和mount阶段的错误会从异步加载流程中重新抛出。建议启用组件内置错误界面或提供自定义错误界面避免产生未处理的 Promise 拒绝。::: warning 启用autoCaptureError或提供#error-boundary插槽后组件会通过错误界面呈现异常不再重新抛出。同一微应用应选择一种错误处理方式不要同时依赖外层errorCaptured与组件内错误边界。详见处理微应用错误。 :::一个值得注意的源码细节为了兼容文档中一直使用的#error-boundary写法组件在读取插槽时会同时接受errorBoundary与error-boundary两种拼写见 MicroApp.ts 中slots.errorBoundary ?? slots[error-boundary]因为 Vue 不会像规范化 prop 名那样规范化插槽名。重新挂载与实例句柄组件仅侦听name的变化来触发重新挂载。修改该 prop 会卸载当前微应用并创建新实例仅修改entry、settings或lifeCycles不会创建新实例。组件销毁时onBeforeUnmount会自动卸载微应用卸载操作会等待正在进行的mountPromise完成以保持挂载和卸载的执行顺序。从源码看挂载/卸载通过一条lifecyclePromise 链串行化unmount().then(() mountMicroApp(...))。源码注释解释了这样做的原因mountMicroApp在应用交接后还要再过一个 tick 才 resolve如果用户在第一次切换尚未落定前又触发了一次name变更没有这条链就可能把两个微应用竞态地挂进同一个容器——这正是router-view在用户快速连点时的典型场景。此外name的 watcher 在触发时会立即快照当时的 props{ ...originProps, ...appProps.value }避免排队的挂载执行时读到更晚一次切换的 props导致最后一个应用被反复挂载又拆掉。可以通过组件实例的microApp和microAppRef两个属性访问当前微应用实例两者均指向同一个MicroAppParcel 句柄。可通过模板 ref 访问该句柄script setup import { ref, onMounted } from vue; import { MicroApp } from qiankunjs/vue; const microAppComp ref(); onMounted(() { // Parcel 句柄getStatus()、mountPromise、unmount()、update() 等 console.log(microAppComp.value?.microApp?.getStatus()); }); /script template micro-app refmicroAppComp nameapp1 entryhttp://localhost:8000 / /template该句柄是qiankunjs/single-spaqiankun 内置的 single-spa fork的 Parcel。getStatus()返回NOT_LOADED、LOADING_SOURCE_CODE、NOT_BOOTSTRAPPED、BOOTSTRAPPING、NOT_MOUNTED、MOUNTING、MOUNTED、UPDATING、UNMOUNTING、UNLOADING、SKIP_BECAUSE_BROKEN或LOAD_ERROR。完整类型参见类型参考。::: tip 由组件管理生命周期 应优先通过 propname、appProps管理微应用而不是直接调用句柄上的unmount()或update()。组件会按顺序执行卸载并协调并发更新直接调用句柄方法可能与组件的内部状态发生冲突。 :::CSS 钩子CSS 类名与 React 绑定一致。组件会添加两个稳定的类名并在提供wrapperClassName或className时将自定义值添加到对应类名之前。元素始终应用的类名prop 提供的额外类名包裹元素仅在启用加载状态或错误边界时存在qiankun-micro-app-wrapperwrapperClassName挂载容器qiankun-micro-app-containerclassName/* 所有微应用的挂载容器 */ .qiankun-micro-app-container { min-height: 320px; } /* 承载加载界面和错误界面的包裹元素 */ .qiankun-micro-app-wrapper { position: relative; }包裹元素仅在启用加载状态或错误边界时存在。因此如果micro-app未配置加载或错误界面wrapperClassName不会产生效果。完整示例以下示例组合了本文介绍的全部核心能力appProps响应式传参、样式隔离、内置加载状态、自定义加载与错误插槽、以及自定义 CSS 类名script setup import { reactive } from vue; import { MicroApp } from qiankunjs/vue; import Spinner from /components/Spinner.vue; import ErrorPanel from /components/ErrorPanel.vue; const appProps reactive({ userId: 42 }); /script template micro-app nameapp1 entryhttp://localhost:8000 :settings{ sandbox: { styleIsolation: true } } :appPropsappProps autoSetLoading wrapperClassNamemy-wrapper classNamemy-container template #loaderloading spinner v-ifloading / /template template #error-boundaryerror error-panel :messageerror.message / /template /micro-app /template组件与 loadMicroApp 的封装关系如果希望脱离组件直接操作实例可阅读loadMicroApp的文档与 核心实现。组件本质上是它的薄封装name、entry对应LoadableApp的name、entry容器由组件内部管理模板 ref 拿到qiankun-micro-app-container的divsettings对应第二个参数AppConfiguration其中sandbox是隔离能力的统一入口对象形式可承载styleIsolation、globals、incubatorContext、plugins等lifeCycles对应第三个参数LifeCyclesappProps经omitSharedProps过滤后作为props传给微应用生命周期。这种封装让你既能享受声明式组件的便利生命周期自动管理、深度侦听更新、加载/错误界面又保留了loadMicroApp全部配置能力需要精细控制时仍可通过microApp句柄拿到 Parcel 级别的状态与 Promise。相关内容ReactMicroApp组件——React 绑定及其 prop 传递方式。loadMicroApp——组件所封装的核心 API。AppConfiguration——settings的类型定义。微应用生命周期与 props——mount、update和unmount的语义。运行多个微应用实例——同时挂载多个微应用。【免费下载链接】qiankun Blazing fast, simple and complete solution for micro frontends.项目地址: https://gitcode.com/gh_mirrors/qi/qiankun创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表