生命周期与运行时
当编辑能力需要接入草稿、发布或线上页面时,把 Schema 看成编辑器和业务服务之间的页面快照。保存时使用 exportSchema();加载时先注册物料,再调用 engine.importSchema(),让当前注册表验证节点和容器。
贯穿示例的仓储契约提供 revision:
ts
export function createMemoryPageRepository(seed: SavedPage[] = []): PageRepository {
const pages = new Map(seed.map(page => [page.id, clonePersistedValue(page)]))
return {
async load(id) {
const page = pages.get(id)
return page ? clonePersistedValue(page) : null
},
async save(input) {
const current = pages.get(input.id)
if (current && current.revision !== input.revision)
throw new PageRevisionConflictError(input.id)
const page: SavedPage = {
id: input.id,
revision: (current?.revision ?? 0) + 1,
schema: clonePersistedValue(input.schema),
}
pages.set(page.id, page)
return clonePersistedValue(page)
},
}
}编辑历史只服务当前浏览器会话。草稿、发布版本、审核记录、乐观锁和权限必须由服务端维护。
生产页面使用自己的运行时组件,而不是编辑 Renderer:
ts
export function createRuntimeNodeRenderer(
componentMap: RuntimeComponentMap,
containerMap: RuntimeContainerMap,
): (node: SchemaNode) => VNodeChild {
const renderNode = (node: SchemaNode): VNodeChild => {
if (node.container) {
const Container = containerMap[node.type]
if (!Container)
return null
const regions = Object.fromEntries(
Object.entries(node.container.regions).map(([regionId, children]) => [
regionId,
children.map(renderNode),
]),
) as RuntimeRegions
return h(Container, {
node,
variant: node.container.variant,
regions,
})
}
const Widget = componentMap[node.type]
return Widget
? h('div', { class: 'guide-runtime-node', style: node.style?.container }, [
h(Widget, { ...node.props, style: node.style?.content }),
])
: null
}
return renderNode
}容器运行时组件接收预先递归生成的 regions,不依赖编辑器的容器上下文:
ts
export const RuntimeColumnContainer = defineComponent({
name: 'GuideRuntimeColumnContainer',
props: {
variant: { type: String, default: 'single' },
regions: {
type: Object as PropType<RuntimeRegions>,
required: true,
},
},
setup(props) {
const renderRegion = (regionId: string) => h('section', {
class: 'guide-runtime-column-container__region',
}, props.regions[regionId] ?? [])
return () => props.variant === 'split'
? h('div', { class: 'guide-runtime-column-container guide-runtime-column-container--split' }, [
renderRegion('left'),
renderRegion('right'),
])
: h('div', { class: 'guide-runtime-column-container' }, [
renderRegion('content'),
])
},
})| 框架负责 | 宿主负责 |
|---|---|
| 快照导入导出、迁移注册、命令校验与编辑历史 | 数据库存储、版本冲突、发布、审核、资源安全与跨端渲染 |
服务端至少校验 node.type、props、资源 URL、页面归属、容器变体和 region 约束。未识别物料必须有可观测的降级或阻断策略,不能静默丢失内容。
完成检查:保存使用 revision 拒绝旧版本;加载先通过当前注册表校验;生产运行时不导入 RootRenderer、ContainerRegionOutlet 或编辑器容器组件。
下一步:按需查阅 API 参考,相关入口见 Designer Schema 与命令。