多窗口
m3-vue 支持分别加载的浏览器窗口,也支持来自同一执行环境、包含 Vue 子树的同源窗口。普通组件和指令会根据自身元素确定 DOM 环境。无论布局库采用跨文档渲染还是移动已有 DOM 节点,使用方都无需了解其实现方式。
UI 所有权
为每个独立拥有 UI 的应用或面板创建一个 overlay host。useOverlays() 会在 setup 期间捕获最近提供的 host 和响应式子树 Snackbar 默认值。在组件外部,createOverlayService(host) 会将两个函数绑定到显式 host。两者都会返回 showDialog(options) 和 showSnackbar(options) 函数,并在异步回调中保留其所有权。仅需通知功能的使用方可使用 useSnackbar()。同一个 Document 中的两个应用仍彼此独立。
滚动锁定、视口监听器、tooltip 事件委托和状态层等 DOM 服务仅在各自 Document 内共享。移除资源所有者后,会释放引用计数资源。每个窗口都必须加载库样式表,以及应用所需的字体和主题;JavaScript 无法将一个 Document 中的样式表应用到另一个 Document。
移动已挂载的面板
布局容器可以将已挂载的面板移入同源 Document,再移回原处,而不卸载 Vue。m3-vue 会在节点被接纳到新文档后重新绑定文档资源。共享的结构观察机制会检测节点从原 Document 移除,无需轮询,也无需为每个组件常驻一个观察器。对于跨任务暂时脱离文档的子树,会通过临时自定义元素的 adoptedCallback 检测其插入新 Document;此过程不使用轮询。
移动时应将完整的交互子树一起移动:触发器、菜单、tooltip 目标及其 host 都应保持在一起。选择器目标会在触发器所属的 Document 中解析。一个窗口中的触发器无法锚定另一个窗口的顶层浮层。移动期间可能会中断临时指针手势;面板到达后请重新开始手势。
程序化调用的所有权跟随 host,而不是键盘焦点。如果面板保留了属于其他 host 的控制器,其程序化调用仍会在那里渲染。Document、Window 和 host 控制器都是运行时对象,不应存入持久化的布局设置。
关闭与卸载
Vue 卸载与浏览器窗口关闭是不同的操作。关闭浏览器窗口不会运行 Vue 卸载钩子。Document 拆除时会释放 m3-vue 资源,并拒绝尚未完成的程序化浮层调用;普通 Vue 卸载则会直接释放所属 host。Vue 应用及其事件处理器、store 和其他运行时资源仍由应用负责处置。
浏览器对顶层、焦点、弹出窗口和后台计时器的原生策略仍然适用。跨源 Document、进程终止和渲染器崩溃无法执行常规 JavaScript 清理,也无法观察 Promise 是否完成。在 Electron 中,窗口必须允许布局容器所需的同源 DOM 访问;m3-vue 不会绕过上下文隔离,也不提供进程间通信。
应用数据共享、状态同步、停靠布局和跨窗口 RPC 仍由应用负责。