--- title: 生命周期与路由拦截 description: 理解结果、队列、Host 生命周期以及路由库适配。 order: 20 toc: - id: result-contracts title: 结果约定 - id: queue title: 队列与 Host - id: dismissal title: 关闭行为 - id: navigation title: 路由拦截 --- ## 结果约定 {#result-contracts} `openConfirm` 使用 `false` 表示取消,`openPrompt` 使用 `null`,自定义 Modal、Sheet 和 Drawer 使用 `undefined` 表示没有结果。`close(value)` 会根据 `openModal()` 的泛型检查结果。 ```tsx import { openModal } from "@workspace/overlays/modal" const productId = await openModal({ title: "选择产品", content: ({ close }) => ( close(product.id)} /> ), }) ``` ## 队列与 Host {#queue} 同一个 Scope 中,每种 feature 都有一个按需创建的 channel 和 Base UI handle。同类调用进入 FIFO 队列,前一个关闭动画结束后才显示下一个。不同 feature 可以同时显示,例如 Modal 内可以继续打开 Confirm。 Host 卸载时会用取消值结算它仍在等待的请求。React Strict Mode 的模拟卸载不会错误取消请求。 ## 关闭行为 {#dismissal} 自定义内容可以调用 `dismiss()`。关闭按钮、Escape 和遮罩点击也进入取消路径。设置 `dismissible: false` 会阻止外部关闭,但内容仍可以显式调用 `close(result)` 或 `dismiss()`。 ## 路由拦截 {#navigation} `@workspace/overlays/navigation` 只依赖 Scope,不依赖具体 overlay feature 或路由库: ```tsx import { OverlayNavigationGuard } from "@workspace/overlays/navigation" const adapter: OverlayNavigationAdapter = { subscribe(listener) { return router.block((transition) => { listener({ cancel: transition.reset, proceed: transition.retry, }) }) }, } ``` 默认 Guard 检查当前和命名局部 Scope,找到最后打开的浮层。如果允许 dismiss,则关闭浮层并取消跳转;`dismissible: false` 会保留浮层并继续阻止跳转;没有浮层时才调用 `proceed()`。 适配器的 `proceed()` 必须继续已经被阻塞的同一次跳转,不能重新发起一个会再次触发 blocker 的导航。需要不同策略时,可以传入自定义 `interceptor`。