Skip to content

生命周期与运行时

当编辑能力需要接入草稿、发布或线上页面时,把 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 拒绝旧版本;加载先通过当前注册表校验;生产运行时不导入 RootRendererContainerRegionOutlet 或编辑器容器组件。

下一步:按需查阅 API 参考,相关入口见 Designer Schema 与命令