多面板布局
状态:Draft 1(预览)—— 抢先体验,不用于生产。 受管布局 API 已交付,但尚未在生产消费方上经受充分检验。字段名、默认值和校验规则在小版本之间仍可能变化。在该标签移除之前,请固定到确切的 CDN 版本。对几乎所有应用而言,标准
compat模式才是推荐的生产模式——只有当你确实需要组合外壳本身时,才动用受管布局。
受管布局模式用完全声明式的面板树取代标准 Wippy 外壳。不再是固定的聊天加侧边栏外壳,你在后端 YAML 中描述一棵具名面板树。Web Host 在启动时组装该布局、校验它,并在运行时以响应式方式维护它。面板可以在不重新加载页面的情况下调整大小、折叠、交换、添加和移除。
何时使用受管布局
标准 compat 模式(默认)为你提供固定的 Wippy 产品形态:导航侧边栏、聊天面板、页面区和右侧产物面板。它是当前使用最广的生产模式,对几乎所有应用都足够。
只有当你需要组合外壳本身时,才选用 fe_mode = managed(抢先体验):
| 需求 | Compat | Managed |
|---|---|---|
| 标准 Wippy 聊天 + 导航 | 有 | 可替换 |
| 多个页面槽位并排 | 无 | 有 |
| 自定义侧边栏或协调器组件 | 受限 | 有 —— 任意面板类型 |
| 按断点的响应式布局 | 无 | 有 |
| 浮动覆盖面板 | 无 | 有 |
| 无头协调器组件 | 无 | 有(coordinators) |
| 逐面板的 URL 感知路由 | 仅主面板 | 每个 kind: page 面板 |
| 跨面板消息总线 | 无 | 有(broadcast/send/on) |
兼容性
受管布局横跨 Web Host、facade 和若干 @wippy-fe/* 包。请为确切的目标 Web Host 发布使用一套兼容的包系列,并核验其提供的 import map;不要混用来自无关发布的包版本。
版本对照
| 发布 | 受管布局新增内容 |
|---|---|
Web Host 1.0.50,Wippy FE 0.0.50 |
类型化 compat intent、@HOST/compat-coordinator、浏览器 URL 与前进/后退同步、内置面板标签页、锚定式浮动面板,以及 useSwapBuffer()。 |
Web Host 1.0.51,Wippy FE 0.0.51 |
响应式且竞态安全的 <wippy-chat> 会话/令牌控制、可选启用的主题化分隔条手柄、仅限分割轴的尺寸约束、抽屉几何/层叠修复,以及打包的 proxy source map。 |
Web Host 1.0.52,Wippy FE 0.0.52 |
类型化的保留式 WC 可见性与 useHostVisibilityRefresh()、立即的页面就绪而非等待 14 秒回退、过期渲染器 key 拒绝、就地组件 prop 更新,以及带 --wippy-layout-splitter-z-index 的独立分隔条层。 |
14 秒页面显现是 Web Host 1.0.52 的回退机制,不是 1.0.51 的特性,也不是应用的加载延迟。分割轴尺寸约束和响应式聊天在 1.0.51 落地;保留式可见性、带 key 的就绪判定和分隔条分层在 1.0.52 落地。
保留式直挂 web 组件的可见性需要 Web Host 1.0.52 以及 @wippy-fe/webcomponent-core、@wippy-fe/webcomponent-vue 和 @wippy-fe/shared 0.0.52。更早的受管布局发布不提供类型化的 data-wippy-visible 契约或 useHostVisibilityRefresh()。
保留式 web 组件的活跃状态
受管布局会在缓冲区交换、断点变化以及抽屉开关周期之间保持面板挂载。宿主在连接直挂自定义元素之前设置 data-wippy-visible="true" | "false",并在逻辑归属变化时就地更新它。这不是 CSS、视口或文档可见性,也绝不意味着重新挂载。
Vue 组件用 useHostVisibility() 读取该状态,或者用 useHostVisibilityRefresh(task) 把常规的初始加载与显现刷新结合起来。后者在挂载后运行,之后只在恰好发生 false -> true 时运行。不要在直挂 WC 中使用 proxy 的 @visibility topic;那是 iframe/Web Fragment 的消息通道。
在 Draft 1 标签移除之前,请固定到确切的 CDN 标签——至少 https://web-host.wippy.ai/webcomponents-1.0.52。
启用受管布局
在 facade 配置中启用受管入口,并提供后端 host_config.layout 声明:
host_config:
layout:
layouts:
default:
direction: horizontal
children:
- panel: nav
size: 240px
- panel: main
size: 1fr
main: true
panels:
nav: { kind: builtin, id: '@HOST/nav-sidebar' }
main: { kind: page, id: home }
选择受管入口后,facade 提供 managed-layout.js 而不是 module.js。fe_mode 是当前的 facade 需求参数(默认 compat,可选 managed);它设置在 wippy.facade 需求上,而不是携带在 AppConfig 载荷内。不存在 AppConfig.feature 字段——受管布局完全通过 AppConfig.hostConfig.layout 传达给子应用。proxy API 的接口面在两种模式下完全相同,但其中一些命令只在其中一种模式下生效——参见各模式下什么能用。
HostLayoutDeclaration
整个布局由单个 HostLayoutDeclaration 对象描述,它嵌套在 facade 配置的后端 host_config.layout 之下,并投射到前端的 AppConfig.hostConfig.layout。宿主在挂载之前校验它——任何 LayoutValidationError 都会以 { kind, message, panelId? } 出现在浏览器控制台中。
| 字段 | 类型 | 说明 |
|---|---|---|
layouts |
Record<string, PanelTree> & { default: PanelTree } |
按断点索引的面板树。default key 是必需的。 |
breakpoints? |
Record<string, number> |
激活非默认布局 key 的像素宽度。 |
panels |
Record<string, HostPanelDef> |
具名面板内容定义。 |
floating? |
Record<string, HostFloatingDef> |
启动时的浮动覆盖面板。 |
modals? |
Record<string, HostModalDef> |
启动时的模态框定义。 |
coordinators? |
Record<string, HostCoordinatorDef> |
无头协调器组件。 |
services? |
Record<string, HostCoordinatorDef> |
coordinators 的已弃用别名;新声明必须使用 coordinators。 |
dragEnabled? |
boolean | 允许用户拖动分隔条。默认 true。 |
面板类型
panels、floating、modals 和 coordinators 中的每一项都是以 kind 为标签的联合类型:
| 类型 | 说明 | 必需字段 |
|---|---|---|
page |
挂载在 srcdoc iframe 中的 Wippy 页面模块 | id(页面注册表 id) |
artifact |
挂载在 srcdoc iframe 中的 Wippy 产物 | id(产物 UUID) |
component |
直接挂载在宿主 DOM 中的 web 组件 | tagName |
builtin |
框架拥有的宿主组件(见下) | id |
布局树中必须恰好有一个面板带 main: true。浏览器 URL 的归属仍然需要通过 @HOST/compat-coordinator 或等价的消费方协调来做路由同步。其他所有面板都在各自的 iframe 内独立路由。
内置面板 ID
kind: builtin 接受以下 id 值。@HOST/ 前缀为框架拥有的面板保留:
| ID | 渲染内容 |
|---|---|
@HOST/nav-sidebar |
标准 Wippy 导航侧边栏(会话、页面、设置) |
@HOST/chat-wrapper |
当前会话的标准 Wippy 聊天面板 |
@HOST/artifact-viewer |
通用产物查看器(与路由 /:uuid 搭配) |
@HOST/session-selector |
会话列表与选择器 |
@HOST/compat-coordinator |
无头的 compat intent 与主路由协调器;声明在 coordinators 下 |
@HOST/panel-tab |
用于展开已折叠面板的边缘标签;声明在 floating 下 |
未知的 @HOST/<id> 会在声明加载时触发 LayoutValidationError,而不是静默渲染一个空槽位。
按断点索引的布局
layouts 字段把断点 key 映射到面板树。除非有更窄的断点匹配,否则始终使用 default。断点的像素宽度定义在 breakpoints 之下:
host_config:
layout:
breakpoints:
sm: 768
layouts:
default:
direction: horizontal
children:
- panel: side
size: 300px
- panel: main
size: 1fr
main: true
sm:
direction: vertical
children:
- panel: main
size: 1fr
main: true
- panel: side
display: drawer-left
drawerSize: { width: 320px }
panels:
side: { kind: page, id: app-sidebar, route: / }
main: { kind: page, id: app-home, route: / }
断点变化时,具有相同 id 的面板保持一个稳定的内容宿主,它在视觉上跟随当前激活的槽位而不做重新挂载父节点的操作。iframe 的 contentWindow、web 组件状态、Vue 状态和滚动位置都能在切换中保留;有意避免通过 Teleport 改变父节点,因为移除并重新插入 iframe 会导致它重新加载。
抽屉模式面板
面板槽位可以声明 display: 'drawer-left' | 'drawer-right' | 'drawer-bottom',从而渲染为滑入式覆盖层而不是内联的 flex 项。抽屉面板:
- 不参与其父容器的轨道尺寸计算(
size被忽略) - 渲染为锚定在指定边缘的绝对定位覆盖层
- 拥有通过
host.layout.openDrawer(id)/closeDrawer(id)/toggleDrawer(id)切换的开关状态 - 打开时显示背景遮罩;点击遮罩会关闭所有已打开的抽屉
main: true 的槽位不能是抽屉模式——宿主校验会抛错。drawerSize.width 字段控制左/右抽屉的宽度;drawerSize.height 控制底部抽屉的高度。默认为 320px。
浮动面板
浮动面板是声明在 floating 之下的自由定位覆盖层。它们不参与 flex 布局树,可以在运行时添加或移除:
floating:
flap:
kind: component
tagName: my-right-flap
position: { x: 0, y: 200 }
size: { width: 48, height: 80 }
运行时管理:
// 添加浮动面板
host.layout.addFloating('inspector', {
kind: 'component',
tagName: 'my-inspector',
position: { x: 100, y: 100 },
size: { width: 400, height: 300 },
})
// 移除它
host.layout.removeFloating('inspector')
无头协调器
协调器是挂载在隐藏宿主中的组件。它们没有可见槽位,但会收到面板作用域的 host API。把横切逻辑放在它们那里,让展示面板专注于渲染。较早的 services 字段仍作为已弃用的兼容别名保留。
coordinators:
coordinator:
kind: component
tagName: my-coordinator
协调器组件收到面板作用域的宿主包装器,并可以在 onMount 中立即订阅总线通道:
import { WippyElement } from '@wippy-fe/webcomponent-core'
class MyCoordinator extends WippyElement {
protected onMount() {
this.host?.layout.on('open-chat', ({ payload }) => {
this.host?.layout.updatePanel('right', { route: `/open-chat/${payload.token}` })
this.host?.layout.expandPanel('right')
})
}
protected onUnmount() {}
static get wippyConfig() { return { propsSchema: { properties: {} } } }
}
customElements.define('my-coordinator', MyCoordinator)
随附的 compat 协调器
受管布局只包含被声明的接口面。因此 host.openArtifact()、host.startChat()、host.openSession() 和 host.navigate() 之类的调用会在保留的 @HOST/intent 通道上发布类型化 intent。声明随附的协调器来处理它们,并把浏览器 URL 绑定到主面板:
coordinators:
compat:
kind: builtin
id: '@HOST/compat-coordinator'
props:
artifactPanel: right
chatPanel: chat
modalId: artifact-modal
routeSync: true
wsActions: true
使用标准导航契约时请保持 routeSync: true。没有协调器或等价的消费方逻辑时,深链接、前进/后退以及 @HOST/nav-sidebar 导航就没有可驱动的面板路由。子应用启动期间产生的 intent 会保存在一个有界队列中,直到第一个协调器订阅为止。
@HOST/ 在两个方向上都是保留的:普通面板不能发布系统流量,而只有 coordinators 下的条目才能通过受支持的 host API 收到它。该边界对 iframe/Web Fragment 面板强制生效。挂载在宿主域中的直挂组件共享宿主 DOM,不构成安全沙箱。启动时,若缺少协调器处理、模态框目标面、主面板 URL 绑定或已声明的协调器标签,宿主会打印一张对照表;声明完整时不会产生警告。
标签页内广播总线
面板通过一条作用域限于当前浏览器标签页的总线通信。该总线绝不跨越到其他标签页——如果你需要多标签页同步,请使用自定义 WebSocket topic。
| 方法 | 说明 |
|---|---|
host.layout.broadcast(channel, payload) |
向所有面板发布;不含发送者 |
host.layout.send(targetPanelId, channel, payload) |
向某一个特定面板发布 |
host.layout.on(channel, handler) |
订阅;返回 off() 取消订阅函数 |
收到消息上的 sourcePanelId 由宿主根据发布窗口设置,无法伪造。通道名称是区分大小写的普通字符串。
重要: 直接从 @wippy-fe/proxy 导入 host 的组件会绕过面板作用域——总线调用仍会发出,但会丢失 sourcePanelId。请始终改用面板作用域的包装器:
// 原始 HTMLElement
import { getWippyHost } from '@wippy-fe/webcomponent-core'
const host = getWippyHost(this)
// WippyElement 子类 —— this.host 已经是面板作用域的
this.host?.layout.broadcast('open-chat', { token: 'abc' })
// Vue 组件
import { useHost } from '@wippy-fe/webcomponent-vue'
// ProxyApiInstance 是环境全局类型(来自 @wippy-fe/types-global-proxy)—— 无需导入即可引用。
const host = useHost<ProxyApiInstance['host']>()
host?.layout.broadcast('open-chat', { token: 'abc' })
布局 API 参考(host.layout)
| 方法 | 说明 |
|---|---|
.snapshot |
同步 getter,返回完整布局快照;在受管布局模式之外为 null |
.resizePanel(id, size) |
在当前断点下调整具名面板的大小 |
.collapsePanel(id) |
折叠声明了 collapsible: true 的面板 |
.expandPanel(id) |
展开已折叠的面板 |
.openDrawer(id) |
打开抽屉模式面板 |
.closeDrawer(id) |
关闭抽屉模式面板 |
.toggleDrawer(id) |
切换抽屉模式面板 |
.movePanel(id, target) |
把面板移动到树中的新位置 |
.removePanel(id) |
从所有断点布局中移除面板 |
.updatePanel(id, def) |
在运行时修补面板定义;props 浅合并,顶层字段整体替换 |
.addFloating(id, def) |
添加浮动面板 |
.removeFloating(id) |
移除浮动面板 |
.openModal(id, def?) |
按 id 打开已声明的模态框,可选择覆盖其定义。仅运行时存在的模态框需要 def。默认使用原生 <dialog>.showModal();传 useNativeDialog: false 可使用旧版 div 覆盖层。重复打开已打开的 id 是静默空操作。 |
.closeModal(id) |
关闭已打开的模态框 |
.broadcast(channel, payload) |
向所有面板发布 |
.send(target, channel, payload) |
向单个面板发布 |
.on(channel, handler) |
订阅总线通道 |
openModal() 记录的是宿主内部的布局基础设施,而不是应用组件的做法范式。交付的 Vue 产品 UI 应当使用 PrimeVue Dialog 或宿主的确认 API,而不是用自定义模态样式克隆这种原生 dialog 行为。
updatePanel 的合并语义
host.layout.updatePanel(id, def) 修补现有的面板定义——它不做整体替换。props 对象会浅合并进面板当前的 props:提供的 key 会被添加或覆盖,未提供的 key 会被保留。def 的其他每一个顶层字段(route、kind、id、tagName、title、icon 等)都会整体替换当前值。
假设某个面板当前的 props 为 { artifactId: 'old', zoom: 2 }:
// props 浅合并 → { artifactId: 'abc', zoom: 2 }
host.layout.updatePanel('right', { props: { artifactId: 'abc' } })
// route 整体替换;props 不受影响
host.layout.updatePanel('right', { route: '/x' })
两点注意:props 合并是浅的——props 内部的嵌套对象会被整体替换,而不是深度合并——而且浅合并无法删除某个 prop key(你只能覆盖它)。
Vue 组合式函数 —— @wippy-fe/vue-host
这些组合式函数把 proxy 布局 API 包装为响应式的 Vue 3 ref。底层订阅是模块作用域的,存活于 iframe 的整个生命周期,因此卸载时没有逐组件的清理:
| 组合式函数 | 返回 |
|---|---|
useWippyLayout() |
完整的布局状态和变更方法 |
useWippyPanel(panelId) |
具名面板的实时状态(panelId 是必需的——string、Ref<string> 或 getter) |
useWippyBreakpoint() |
以响应式 ref 表示的当前激活断点名称 |
useWippyMainRoute() |
指向主面板当前路由的响应式 ref |
这些组合式函数从不返回 null——它们始终返回对象/ref,当不存在受管布局宿主时其内部的 .value 会降级:useWippyLayout().snapshot.value 为 null(且 isManaged.value 为 false,因此变更是静默空操作),useWippyBreakpoint().value 和 useWippyMainRoute().value 为空字符串,而当 id 不存在时 useWippyPanel(id).value 为 null。请用 layout.isManaged.value(或 layout.snapshot.value !== null)判断宿主是否存在,而不要对返回值做 === null 检查。这使得这些组合式函数在没有受管布局宿主的独立 playground 和单元测试中仍然可用。
无重新挂载的交换缓冲
@wippy-fe/layout 的 useSwapBuffer() 在新内容报告就绪之前保持旧的展示面挂载,并设有明确的超时上限。用不可变的 slot.index 作为 DOM key,把索引和内容 key 一起传给 markReady() / markFailed(),以便拒绝过期的异步信号,并把错误按缓冲区隔离。内容标识属于 keyOf;改变 DOM key 会重新插入 iframe,从而摧毁缓冲本要保留的状态。
const swap = useSwapBuffer<Surface>({
keyOf: surface => surface.ownerId,
buffers: 2,
readyTimeoutMs: 8_000,
loaderDelayMs: 250,
loaderMinMs: 400,
})
const slot = swap.push(surface)
swap.markReady(slot.index, slot.key)
// 或:swap.markFailed(slot.index, error, slot.key)
上面展示的是默认值。就绪超时默认会显现内容,而不是把过期内容留在加载器之后。请把加载 UI 绑定到 swap.showLoader,而不是直接绑定到就绪状态。失败的缓冲区与其同级保持隔离;处理完错误后调用 clearError(index) 重试。
Web Host 页面就绪
Web Host 对受管页面展示面采用同样的带 key 就绪纪律,并设有 14 秒的最终显现上限。iframe 和直挂 Web Component 渲染器通过 Vue 事件监听器发出 load / error,并附带该渲染器所拥有的不可变内容 key。因此已绘制的内容会被立即显现;该上限只是针对从不报告的内容的回退。当某个被驱逐渲染器的缓冲区索引已被复用时,它的迟到事件会被拒绝。
不要把 14 秒的宿主上限当作应用的加载延迟,也不要围绕正常的页面就绪再加一个计时器。经常触及该上限的页面,其就绪或生命周期路径已经损坏,应当在其归属处修复。
稳定的组件更新与面板尺寸
对于 kind: component,改变面板 props 会更新或移除现有自定义元素上的属性。只有 tagName 变化时宿主才会替换该元素。这在 updatePanel() 调用和断点切换期间保留了元素自身拥有的状态。
minSize 和 maxSize 只约束当前的分割轴:水平树中是宽度,垂直树中是高度。它们不限制交叉轴,因此导航、聊天和其他满高挂载可以填满自己的轨道。抽屉挂载遵循带动画的抽屉几何,仅在打开时被提升到其锚点和背景遮罩之上,且不重新挂载其内容。
分隔条与手柄样式
分隔条的命中区域比它的可见线条更宽,并位于该包独立的层叠栈中。--wippy-layout-splitter-z-index 默认为 700,低于抽屉和模态框背景遮罩。圆形手柄需要主动启用:
| 变量 | 默认值 | 用途 |
|---|---|---|
--wippy-layout-splitter-size |
1px |
可见分隔线粗细 |
--wippy-layout-splitter-hit-size |
10px |
线条周围的指针命中区域;粗指针下为 24px |
--wippy-layout-splitter-z-index |
700 |
分隔条与手柄所在层 |
--wippy-layout-splitter-handle-size |
0 |
手柄直径;0 表示禁用 |
--wippy-layout-splitter-handle-bg |
transparent |
手柄填充 |
--wippy-layout-splitter-handle-border |
0 solid transparent |
border 简写 |
--wippy-layout-splitter-handle-shadow |
none |
手柄阴影 |
--wippy-layout-splitter-handle-icon-color |
transparent |
通过 currentColor 实现的主题感知 SVG 颜色 |
启用时请同时设置尺寸、填充、边框/阴影和图标颜色。SVG 在垂直分隔条上会旋转 90 度,在锁定的分割处保持隐藏。
各模式下什么能用
proxy API 的接口面在 compat 和 managed 模式下完全相同——同样的 @wippy-fe/proxy 导入在两种模式下都能解析——但其中两部分的实际效果与模式相关。把应用迁到受管布局时,这种不对称是最需要留意的地方(也是 managed 仍处于抢先体验阶段的一个原因)。
host.layout 只在受管模式下生效
宿主只有在声明了布局时才安装布局接收器(受管入口,以 hostConfig.layout 为门控)。在 compat 模式下 host.layout 仍然存在,但 host.layout.snapshot 为 null,并且每一个变更和总线调用(resizePanel、updatePanel、movePanel、openModal、addFloating、broadcast、send、on 等)都是静默空操作——消息被投递了,但宿主上没有任何东西在监听。变更之前请以快照为门控:
if (host.layout.snapshot) {
host.layout.updatePanel('right', { route: '/details' }) // 仅受管模式
}
// Vue:const { isManaged } = useWippyLayout(); if (isManaged.value) { … }
(另外一个维度的问题——addPanel 和 setLayout 根本没有通过 proxy 暴露,两种模式下都没有;参见已知局限。)
假定存在 compat 外壳的 host.* 命令
受管外壳只渲染你声明的布局。从 Web Host 1.0.50 起,那些通常面向 compat 外壳的命令会改为发布类型化的 @HOST/intent 消息,而不是静默失败。请声明 @HOST/compat-coordinator 或实现等价的协调器,把这些 intent 映射到你的面板:
host.* 命令 |
Compat(默认) | Managed |
|---|---|---|
setContext、toast、confirm、handleError、logout、bridge.*、顶层 state / ws / on |
可用 | 直接可用;受管模式会挂载全局 toast 和确认面 |
openArtifact(id, ...) |
在右侧面板或模态框中打开 | 发布一个 intent;compat 协调器指向 artifactPanel 或 modalId |
startChat(token) / openSession(uuid) |
打开并显示会话 | 发布一个 intent;compat 协调器解析启动令牌并更新已声明的 chatPanel |
navigate(url) |
推入 compat 根路由器 | 发布一个 intent;routeSync 把它应用到主面板并保持浏览器历史一致 |
onRouteChanged(route, navId?) |
驱动宿主浏览器 URL | 更新面板路由状态;routeSync 把主面板路由投射到浏览器 URL |
如果尚无可用的协调器,启动时的 intent 会保存在一个有界队列中,等待第一个协调器订阅。声明了却没有处理器的情况会由启动对照表报告。保留 intent 只能被 coordinators 条目读取,普通面板无法伪造。
状态管理方式
三个层次,按优先顺序:
路由 —— 如果用户可能有意义地收藏或分享该状态,就把它放进 URL。每个 kind: page 面板运行自己的路由器并响应 @history 事件。这种方式解耦、可深链接,并且感知浏览器历史。
布局快照 —— 如果它影响布局形态(尺寸、折叠标志、组件 props),就通过 updatePanel 或 resizePanel 放进快照。每个订阅的面板都会看到每一次快照变化,因此请保持载荷小巧。
面板本地 —— 其余一切(表单草稿、模态框状态、临时 UI)都留在面板自己的 Pinia store 或 ref 中,绝不离开该面板。
标准协调范式
跨面板交互的推荐范式是:总线事件 → 协调器服务 → updatePanel → 面板通过自己的路由器响应。
// 在协调器服务中
this.host?.layout.on('open-chat', ({ payload }) => {
this.host?.layout.updatePanel('right', { route: `/open-chat/${payload.token}` })
this.host?.layout.expandPanel('right')
})
// 在右侧面板应用中(一个普通的 Vue 页面模块)
const router = createAppRouter([...])
// createAppRouter 已经把宿主的 history 事件镜像进路由器,
// 并带有回声/当前路由守卫;不要再添加手动的路由订阅。
保持协调器轻薄。让面板拥有自己的 UI。
已知局限
截至 Draft 1,以下内容尚未实现:
- 通过 proxy 使用
addPanel/setLayout—— 未交付。它们只存在于内部的@wippy-fe/layoutLayoutManager上,未跨 iframe proxy 边界暴露。(openModal、closeModal和movePanel已交付——参见布局 API 参考。) - 面板拖拽重排 UI —— 数据模型和
movePanel()API 可用;面向用户的拖拽尚未实现。 - 标签页原语 —— 尚未实现。
- 网格瓦片容器 —— 已列入后续计划。
- 运行时变更的持久化 —— 变更不会跨重新加载持久化。如有需要请手动持久化:
on('@layout-change', () => state.set('layout', host.layout.snapshot) ) nav-sidebar头部插槽扩展点 —— 在本草案中,logo、应用名和切换按钮的位置是固定的。
另请参阅
- Facade 入口点 —— facade 如何加载 JS 模块入口并交付配置
- 引导序列 —— 宿主在启动时如何派发到受管布局入口
- 包 ——
@wippy-fe/layout、@wippy-fe/vue-host、@wippy-fe/webcomponent-core、@wippy-fe/webcomponent-vue