生命周期与所有权
应用的注册、mount、动态 props、卸载、keep-alive 与资源清理。
版本、变更与要求见 Framework 3.2 与 CLI 1.0。
注册不等于挂载
wu.init 注册元数据和权限。wu.define 注册函数。wu.mount 解析应用、准备容器,在缺少定义时加载 entry,然后执行 renderer。名称将这三个步骤关联起来。
import { wu } from 'wu-framework';
let stop = () => {};
let abort = null;
wu.define('activity', {
mount(container, { wu: appWu }) {
abort = new AbortController();
const output = document.createElement('output');
const refresh = () => {
output.textContent = String(appWu.store.get('activity.count') ?? 0);
};
container.replaceChildren(output);
stop = appWu.store.on('activity.count', refresh);
refresh();
container.addEventListener('click', () => {
appWu.emit('activity:opened', { source: 'counter' });
}, { signal: abort.signal });
},
update(container, props) {
container.setAttribute('aria-label', props.label ?? 'Actividad');
},
unmount(container) {
stop();
abort?.abort();
container.replaceChildren();
},
});
应用需要相应请求和 grants 才能读取 activity.count 并发射 activity:opened。示例保留收到的 facade;导入的 wu 用于注册生命周期。
可用 slots
| Slot | 签名 / 用途 |
|---|---|
mount |
(container, { appName, wu });必需 |
unmount |
(container, context);释放 renderer、监听器和自有资源 |
update |
(container, nextProps);无需卸载即可更新 |
hydrate |
(container, { appName, wu, props });接管 SSR 标记 |
deactivate |
(container);通过 keep-alive 隐藏前调用 |
activate |
(container);重新激活保留的应用 |
slots 支持 Promise。mount 中的 Promise 拒绝后,core 可以清理本次尝试并调用恢复机制。吞掉错误却不渲染任何内容,可能让 WU 将挂载视为成功;确实无法挂载时应抛出错误。
可观察的执行顺序
挂载依次执行 beforeLoad、插件 beforeMount hook、创建 sandbox、执行 afterLoad、获取或加载定义、执行 beforeMount、等待样式,然后调用 hydrate 或 mount。随后记录已挂载状态并执行后续 hooks。
afterLoad 在创建 sandbox 后、解析或加载生命周期前执行。需要对已挂载的树作出响应时,使用 afterMount。
core 将同一容器上的状态转换串行化。应用不应删除所有权已转移给其他应用的节点。系统还提供引用计数和延迟卸载,以吸收 React StrictMode 等集成周期。如果多个使用方共享一个应用,每次挂载都应有对应的卸载。
动态 props
const updated = await wu.update('activity', { label: 'Actividad reciente' });
if (!updated) console.info('La app no aplicó esta actualización');
如果应用未实现 update slot,它不会凭空创建 renderer。React 和 Vue adapters 保留 props,并在不重新挂载的情况下更新根节点。初始 props 在 adapter 注册或 SSR 中配置;常规挂载的 WuLifecycle.mount 未声明 context.props。
隐藏与销毁
await wu.hide('activity');
console.log(wu.isHidden('activity'));
await wu.show('activity');
await wu.unmount('activity', { force: true });
hide 保留 DOM、已有 iframe、状态、timers 和监听器。应用仍会占用资源;可在 deactivate 中暂停隐藏期间不需要的自有工作。show 恢复可见性并执行 activate,不会重新加载 entry。
unmount 按以下顺序决定 keepAlive:force 强制销毁;否则先采用本次调用选项,其次是应用配置,最后为 false。完整卸载会撤销 scoped 身份及关联的监听器和 handlers。卸载后保留的 context.wu 引用会以 WU_APP_SCOPE_REVOKED 失败。
wu.destroy() 清理整个运行时。应在 shell 结束时使用,而不是只切换一个区域。wu.app(name, config) 返回含 mount、unmount、hide、show、remount、reload、verify、start、stop 和 destroy 的 wrapper。
Wrapper:延迟注册与并发
wu.app(name, config) 将应用身份、配置和目标组合在一起。创建 wrapper 会保存这些数据;实际注册发生在挂载时,由 core 验证 manifest 和权限。如果 core 尚未启动,wrapper 会先用该配置初始化,再挂载。
const widget = wu.app('widget', {
url: '/apps/widget',
container: '#widget-slot',
framework: 'vue',
grants: [],
});
await widget.mount();
console.log(widget.isMounted, widget.info.container);
await widget.hide();
await widget.show();
await widget.unmount({ force: true });
URL 必须提供 widget 的 manifest。mount(selector) 可选择其他目标,并保存它,供后续无参数调用使用。挂载、卸载、可见性、remount 和 reload 方法都解析为同一个 wrapper,方便结束后检查状态。
| 成员 | 用途 |
|---|---|
mount(selector?) / start(selector?) |
必要时注册,并挂载到字符串选择器指定的位置 |
unmount(options?) / stop() |
卸载;stop 使用默认选项 |
hide() / show() |
保留并重新激活已挂载应用 |
remount(selector?) |
强制卸载后重新挂载 |
reload() |
卸载,清除可用的 loader/manifest 缓存,然后重新挂载 |
isMounted / isHidden |
查询 wrapper 和 core 状态 |
info |
名称、URL、选择器、挂载情况和 status |
verify() |
检查注册、选择器和容器 Shadow DOM |
如果另一个 init 正在进行,wrapper 会等待它完成,之后在应用仍未注册时注册。同一个 wrapper 上的两个并发 mounts 共享注册 Promise;每次挂载仍参与 core 的所有权与引用计数。失败会释放该 Promise,以便重试。保留宿主已有的注册,不会用另一个 wrapper 的 grants 覆盖它。
reload() 不会使浏览器原生 ESM 模块缓存失效,也不保证同一 URL 会下载不同版本。更新已部署版本时,应发布带构建身份的 entries,并由 shell 协调加载。
verify().container.hasContent 检查 slot 的 ShadowRoot 子节点;false 不能证明拥有自身 DOM 所有权或使用 light DOM 的 renderer 为空。WuApp.destroy() 从公开映射中删除应用,但不会清理所有关联的 manifest 注册。移除 renderer 使用 unmount;重新初始化整个 shell 使用 wu.destroy() 后再次 init,不要将 wrapper 的 destroy 当作通用的身份替换操作。
实现参考
Slots:src/index.d.ts;定义:src/core/wu-core.js;挂载:src/core/wu-core.js;更新:src/core/wu-core.js;拆卸:src/core/wu-core.js;keep-alive:src/core/wu-core.js;wrapper:src/core/wu-app.js。测试:tests/unit/keep-alive.test.js、tests/unit/props-channel.test.js、tests/unit/shared-container-navigation.test.js、tests/unit/scoped-events-teardown.test.js。