文档/ API

Runtime API

从创建实例到响应事件,按开发任务查找接口。每项包含类型签名、参数说明与使用建议。

Runtime 基础

Runtime 基础

先创建运行边界,再在其中创建、查询和销毁 Instance;同一个 Runtime 可共享 App、资源池与宿主能力。

Function

createFlamoRuntime

独立页面 ↗#

创建一个新的 Runtime 控制面,用于配置并管理一组 Instance 的注册表、App 复用、资源池与宿主能力。

类型
createFlamoRuntime(options?: FlamoRuntimeOptions): FlamoRuntime

Runtime 是什么

Runtime 是 Flamo 在宿主应用中的长期运行边界。一个编辑器、画布区域或具有共同生命周期的页面区域,通常对应一个 Runtime。它负责把可持久化的 Artifact 变成可交互内容,并统一管理这一运行域里的资源与对象。

通过 createFlamoRuntime(options),可以配置该运行域使用的 canvas、App 默认参数、组件解析器、宿主服务、模块策略和 ResourcePool。创建之后,Runtime 提供一组完整的控制能力:

  • 使用 runtime.create() 创建 Instance,并可通过其中的 target 在创建阶段绑定宿主;
  • 使用 runtime.mount(target, artifact) 创建并挂载新的 Instance;
  • 使用 runtime.get() / runtime.list() 查询当前运行域中的对象;
  • 使用 runtime.inspect() 获取可观测快照;
  • 使用 runtime.destroy() 结束对象生命周期并释放其引用;
  • 使用 runtime.probeCapabilities() 检查当前宿主支持的能力。

Runtime 还决定一组内容如何共享 App、ECS world、渲染循环和资源缓存。它适合由宿主持有,并随着编辑器、画布或页面区域的整体生命周期创建和释放。

mount() 属于 Runtime,不属于返回的 FlamoInstance。如果先调用 runtime.create({ artifact }) 且未提供目标,不能再调用 instance.mount(target);应在创建选项中传入 target,或直接使用 runtime.mount()。

同一个 Runtime 内共享 App 的优势

默认情况下,Runtime 会让其 Instance 共享同一个底层 Flamo App。这个层级复用的是 ECS world、SceneRuntime、渲染循环、Canvas surface 管线和 App 使用的资源池,而不是把所有 Instance 合并成一个实例。

具体收益是:

  • 创建多个 Instance 时不需要为每个实例重复初始化 App、ECS world 和渲染循环。
  • 相同图片或视频可通过内容寻址 registry 复用已解码、已上传的 GPUTexture,减少重复加载与显存占用。
  • App 默认在最后一个 Instance 销毁后继续保活,后续重新挂载可复用已有 world,避免重复初始化并提高 remount 稳定性。
  • Instance 仍保留独立的 idMap、selector、props、bindings 和生命周期;共享资源不会让同名节点或交互串到其他实例。

shareApp: false 会让每次 runtime.create() 使用独立 App。只有确实需要独立 ECS world、渲染循环或故障边界时才这样配置。

多个 Runtime 共享 ResourcePool

多个画布需要独立 Runtime/App 时,可以只共享更底层的 ResourcePool:

import {
createResourcePool,
createFlamoRuntime,
} from '@flamo/runtime';
const resourcePool = createResourcePool();
const leftRuntime = createFlamoRuntime({
canvas: leftCanvas,
shareApp: false,
resourcePool,
});
const rightRuntime = createFlamoRuntime({
canvas: rightCanvas,
shareApp: false,
resourcePool,
});

这时左右画布拥有独立的 App、ECS world、SceneRuntime、selector 和事件状态,但共同复用:

  • 同一次 GPUAdapter / GPUDevice 初始化;
  • 按 hash 缓存的图片解码结果与 GPUTexture;
  • 视频元素、视频帧纹理和媒体注册表;
  • image:、font:、module:、html: 等资源引用的解析结果;
  • 按 Runtime / Instance / source node 记录的资源 retain/release 所有权。

这比“每个画布完整创建一套 GPU 和媒体资源”更省初始化成本与内存,同时又比共享整个 App 提供更强的场景隔离。

外部传入的 ResourcePool 由宿主持有;应在所有使用它的 Runtime 和 Instance 都结束后再调用 resourcePool.destroy()。资源复用会延长缓存存活时间,因此它是在初始化成本、内存驻留和隔离强度之间做出的明确选择。

最小用法

const runtime = createFlamoRuntime();
const instance = await runtime.mount(container, artifact);
// 宿主卸载时
await runtime.destroy(instance);

常见误区

  • 不要为了渲染每个组件都新建 Runtime;同一生命周期域的一组 Instance 通常应由同一个 Runtime 管理。
  • shareApp 与 resourcePool 不是同一层:前者共享 App/world,后者可以在 App/world 隔离时只共享 GPU 与媒体资源。
  • 不要在仍有 Runtime 使用 ResourcePool 时销毁它。

参数

options?
FlamoRuntimeOptions
返回 FlamoRuntime来源 runtime/src/2d/framework/index.ts:10044
Interface

FlamoRuntime

独立页面 ↗#

拥有 Instance 注册表、资源边界、组件解析和检查能力的运行时接口。

类型
export interface FlamoRuntime

Runtime 是一组 Instance 的 owner。通过同一 Runtime 创建、查询和销毁实例;需要画布或租户隔离时,使用不同 Runtime。

runtime.mount(target, artifact, options) 等价于 runtime.create({ ...options, target, artifact }):两者都返回新 Instance,区别是前者把目标作为独立的第一个参数。挂载发生在创建阶段;返回的 FlamoInstance 不提供 mount(target)。

const first = await runtime.mount('#first', artifact);
const second = await runtime.create({ target: '#second', artifact });

runtime.get() / list() / inspect() 只读取这个 Runtime 的注册表,runtime.destroy() 只销毁由它登记的 Instance。父子图的 mountChild() 和 mountComposition() 属于 Instance API,不是 Runtime 的 DOM 挂载入口。

返回 —来源 runtime/src/2d/framework/index.ts:2443
Interface

FlamoRuntimeOptions

独立页面 ↗#

配置 Runtime 的默认 App、资源池、组件解析器、服务与共享策略。

类型
export interface FlamoRuntimeOptions

一般示例可以使用默认值。只有在多画布、离线资源、精确组件解析或宿主服务治理场景下,才应逐项覆盖这些选项。

两种共享策略

选项 共享层级 保持隔离的内容 主要收益
shareApp: true 同一 Runtime 内共享 App、ECS world、SceneRuntime、渲染循环和资源池 每个 Instance 的节点映射、props、bindings 与生命周期 多实例避免重复初始化整套 App
多个 Runtime 使用同一 resourcePool 只共享 GPU device、图片/视频 registry 和资源解析缓存 各 Runtime 的 App、world、selector、事件与实例注册表 多画布保留场景隔离,同时减少 GPU 与媒体资源重复

未自定义 createApp 时,shareApp 默认为 true。destroySharedAppOnIdle 默认为 false,所以最后一个 Instance 销毁后 App/world 仍保活,便于稳定、快速地重新挂载;它不会阻止 Instance 自身的 scene、selector、binding 和 surface 引用被清理。

当 Runtime 接收外部 resourcePool 时,Runtime 不拥有它的最终销毁权。宿主应在所有使用者结束后统一调用 resourcePool.destroy()。

返回 —来源 runtime/src/2d/framework/index.ts:2338
Function

probeFlamoPlatformCapabilities

独立页面 ↗#

生成指定宿主平台与 Runtime 版本对应的能力清单。

类型
probeFlamoPlatformCapabilities(platform?: "web" | "weixin" | "ssr" | "worker" | "worklet" | "native" | string & { ... }, runtimeVersion?: string): FlamoPlatformCapabilityManifest

在加载需要特定平台能力的组件或组合前进行探测。结果是能力声明,不等同于实际业务资源或权限已经可用。

参数

platform?
"web" | "weixin" | "ssr" | "worker" | "worklet" | "native" | string & { ... }
runtimeVersion?
string
返回 FlamoPlatformCapabilityManifest来源 runtime/src/2d/framework/platform/PlatformCapabilities.ts:79

Artifact 与组件

Artifact 与组件

Artifact 是可序列化定义;Component 是生成并封装 Artifact 的可复用代码 API;二者都要交给 Runtime 才会产生 Instance。

对象模型

Artifact 不等于 Component

Artifact 是可以保存和传输的结构化定义;Component 是接收 props、生成 Artifact 的可复用代码 API; Runtime 把 Artifact 创建或挂载后,才会得到一次运行所对应的 Instance。

Artifact 内的 exports 表示它公开的组件边界;JavaScript 的 export 则用于导出 Component API。两者不是同一层的“导出”。

对象如何定义与导入如何导出如何实例化
ArtifactJSON、ES Module 或生成器输入,经 defineFlamoArtifact() 规范化保存为 JSON,或作为普通 JavaScript 值导出runtime.create({ artifact }) 或 runtime.mount(target, artifact)
Component用 createFlamoComponentApi(factory) 定义,再通过 ES Module 导入export const Card = ...Card.create(props)、Card.mount(target, props),或调用 runtime.create({ artifact: Card(props), props })
Instance由 Runtime 返回;同一 JavaScript realm 内可通过 ES Module 共享活引用,但不是可导入的组件定义可以导出活对象引用;不能序列化、跨进程传输或作为组件发布物,应另存 Artifact、Component 模块和 props由上述 create() / mount() 调用产生

查看如何构造父子层级并把多个组件封装为新组件 →

Function

defineFlamoArtifact

独立页面 ↗#

规范化结构化输入,得到可由 Runtime 挂载的 Flamo Artifact。

类型
defineFlamoArtifact(input: FlamoArtifactLike, options?: DefineFlamoArtifactOptions): FlamoArtifact

它是手写、导入或代码生成 Artifact 的入口。输入应只包含可持久化事实,不要写入 DOM、ECS Entity 或某次运行产生的对象引用。

导入 Artifact

Artifact 可以来自 JSON 文件、网络接口或 ES Module。导入后先经过 defineFlamoArtifact(),可统一补齐 schema、metadata、exports 等规范字段:

import artifactJson from './card.flamo.json' with { type: 'json' };
import { defineFlamoArtifact } from '@flamo/runtime';
export const cardArtifact = defineFlamoArtifact(artifactJson);

从网络读取时同样处理:

const source = await fetch('/artifacts/card.flamo.json').then(response => response.json());
const cardArtifact = defineFlamoArtifact(source);

导出 Artifact

Artifact 是普通的可序列化数据,可以保存成 JSON,也可以作为 JavaScript 值导出:

const json = JSON.stringify(cardArtifact, null, 2);
export default cardArtifact;

导出的 Artifact 仍只是定义。要运行它,需要调用 runtime.create({ artifact: cardArtifact }) 或 runtime.mount(target, cardArtifact)。

参数

input
FlamoArtifactLike
options?
DefineFlamoArtifactOptions
返回 FlamoArtifact来源 runtime/src/2d/artifact/FlamoArtifactFactory.ts:54
Interface

FlamoArtifact

独立页面 ↗#

Flamo 可持久化设计、组件、行为和资源事实的规范化容器。

类型
export interface FlamoArtifact

Artifact 可以版本化、传输和验证;Instance 才拥有运行态状态。

Artifact 不是 Component 的同义词

Artifact 是结构化数据容器,可以描述一个组件,也可以描述完整页面、场景或其他可运行内容。它本身不要求具备 props factory、代码模块或组件级发布身份。

Component 则是在 Artifact 之上建立的可复用代码入口:它接收 props、生成 Artifact,并提供创建、挂载和公共契约查询能力。使用 createFlamoComponentApi(factory) 可以把 Artifact factory 定义为 Component API。

因此三者的关系是:

Component(props) → Artifact → Runtime.create()/mount() → Instance

如果手上已有 Artifact,可以直接交给 Runtime,不必先把它包装成 Component。只有需要 props、重复使用、模块导入导出或稳定公共接口时,才需要定义 Component。

完整概念边界见 Artifact、Component 与 Instance。

需要把多个子组件按父子层级封装为新的 Artifact / Component 时,使用 Composition IR,而不是保存运行中的 Instance。完整步骤见 组合多个组件并封装为新组件。

返回 —来源 runtime/src/2d/artifact/types.ts:385
Function

createFlamoComponentApi

独立页面 ↗#

把接收 props 并生成 Artifact 的 factory 定义为可导入、可创建、可挂载的 Component API。

类型
createFlamoComponentApi(factory: FlamoArtifactFactory<P>, defaults?: { ... }): FlamoComponentApi<P>

定义一个 Component

Artifact 负责描述内容,Component API 负责把这份描述变成可复用的代码入口。先准备一个 Artifact 或 Artifact factory,再用 createFlamoComponentApi() 包装:

import { createFlamoComponentApi } from '@flamo/runtime';
import cardSource from './card.flamo.json' with { type: 'json' };
export const Card = createFlamoComponentApi(
({ title = 'Card' } = {}) => ({
...cardSource,
metadata: {
...cardSource.metadata,
name: title,
},
}),
);

factory 返回的仍是 Artifact 数据。createFlamoComponentApi() 会负责规范化它,并返回同时支持调用、创建、挂载和契约查询的 FlamoComponentApi。

如果 Artifact 内部声明了一个或多个组件边界,artifact.exports 记录这些公开边界,artifact.metadata.mainExport 指定默认边界。这里的 artifact.exports 是 Artifact 内的组件公开表,不要和 JavaScript 的 export 语法混淆。

导入并实例化

Component API 是 JavaScript 模块导出,可以像普通模块一样导入:

import { Card } from './Card.js';
// 只生成 Artifact,不启动运行态
const artifact = Card({ title: '账户卡片' });
// 使用 @flamo/runtime 的默认 Runtime 创建或挂载 Instance
const created = await Card.create({ title: '账户卡片' });
const mounted = await Card.mount('#preview', { title: '账户卡片' });

需要使用指定 Runtime 时,不调用 Component API 自带的 .create() / .mount(),而是先生成 Artifact,再交给目标 Runtime:

const props = { title: '账户卡片' };
const artifact = Card(props);
const instance = await runtime.create({ artifact, props });
// 或直接挂载
const mounted = await runtime.mount(container, artifact, { props });

runtime.create() 与 Card.create() 的区别

调用 Artifact 从哪里来 使用哪个 Runtime props 如何进入运行态
Card.create(props, options) Card 的 factory 自动生成 模块内置的默认 Runtime 自动写入创建选项
runtime.create({ artifact, props, ...options }) 调用方显式提供 当前这个 runtime 调用方显式提供

Card.create() 适合使用默认 Runtime 的组件消费代码;runtime.create() 适合编辑器、多画布或需要独立资源与实例注册表的宿主。使用自定义 Runtime 时,不要先调用 Card.create(),而应调用 Card(props) 取得 Artifact,再交给目标 Runtime。

导出边界

  • 导出 Artifact:保存组件定义的数据,可用于传输、验证和版本化。
  • 导出 Component API:导出 factory 与便捷方法,适合在 JavaScript/TypeScript 工程中复用。
  • 导出 Instance 活引用:仅适合同一页面、同一 JavaScript realm 内的模块协作,必须由 owner 管理创建与销毁。
  • 不把 Instance 当作发布物:它不能序列化、跨环境传输或供其他项目再次实例化;跨环境复用必须由目标 Runtime 根据 Artifact 或 Component API 重新创建。

参数

factory
FlamoArtifactFactory<P>
defaults?
{ ... }
返回 FlamoComponentApi<P>来源 runtime/src/2d/framework/index.ts:10097
Function

createFlamoWrapperContract

独立页面 ↗#

把 Artifact 的公开 surface 投影成 Custom Element wrapper 契约。

类型
createFlamoWrapperContract(artifact: FlamoArtifact, options?: CreateFlamoWrapperContractOptions): FlamoWrapperContract

用于打包或宿主适配阶段生成 attributes、properties、events 等 W3C 接口描述。它描述契约,不负责注册元素或创建 Runtime Instance。

参数

artifact
FlamoArtifact
options?
CreateFlamoWrapperContractOptions
返回 FlamoWrapperContract来源 runtime/src/2d/artifact/FlamoArtifactFactory.ts:89
Interface

FlamoWrapperContract

独立页面 ↗#

Artifact public surface 到 W3C Custom Element 的稳定投影结果。

类型
export interface FlamoWrapperContract

契约区分 attribute 可表达的字符串值与 property 可承载的结构化值,并记录公开事件。它是包装器生成事实,不是框架适配层。

返回 —来源 runtime/src/2d/artifact/FlamoArtifactFactory.ts:39
Interface

FlamoComponentApi

独立页面 ↗#

把组件 Artifact factory、创建、挂载和契约查询收敛为一个调用接口。

类型
FlamoComponentApi(props?: P): FlamoArtifact

它适合为代码创作的组件提供一致入口:

调用 结果
Card(props) 生成一个规范化 Artifact
Card.artifact(props) 显式生成同一个 Artifact
Card.create(props, options) 使用模块默认 Runtime 创建 Instance
Card.mount(target, props, options) 使用模块默认 Runtime 创建并挂载 Instance
Card.contract(props) 读取组件面向宿主的 wrapper contract

.create() 和 .mount() 使用 @flamo/runtime 的默认 Runtime。需要指定 Runtime 时,先生成 Artifact,再显式交给目标 Runtime:

const props = { title: '账户' };
const artifact = Card(props);
const instance = await runtime.create({ artifact, props });

Card.mount() 属于 Component API:它先生成 Artifact,再委托默认 Runtime 创建并挂载一个新 Instance。它不是返回对象上的方法;const instance = await Card.create(...) 之后不能调用 instance.mount(target)。

Component API 是普通 JavaScript 值,可以使用 ES Module 导入导出并作为可复用创建入口。Instance 则是调用后产生的运行态句柄:同一 JavaScript realm 内可以导入导出它的活引用,但不能随组件模块一起序列化、发布或跨环境恢复。

createFlamoComponentApi() 负责把一个 Artifact factory 变成便捷调用入口,但不会把若干 live Instance 自动编译成新组件。多组件层级应先使用 defineFlamoComponent() 构造 Composition IR,再生成新的 Artifact。参见 组合多个组件并封装为新组件。

参数

props?
P
返回 FlamoArtifact来源 runtime/src/2d/framework/index.ts:1934

Instance 生命周期

Instance 生命周期

Instance 是 Artifact 或 Component 在某个 Runtime 中运行后的临时句柄,用于交互、检查与销毁。

Function

create

独立页面 ↗#

通过模块内置的默认 Runtime 创建一个 Flamo Instance;它是 flamo.create(options) 的快捷入口,不会新建 Runtime。

类型
create(options: FlamoCreateOptions): Promise<FlamoInstance>

它实际做了什么

顶层 create(options) 等价于:

return flamo.create(options);

其中 flamo 是 @flamo/runtime 在模块加载时创建的默认 Runtime 单例。因此每次调用 create() 只会创建新的 Instance,不会创建新的 Runtime。

import { create, destroy } from '@flamo/runtime';
const instance = await create({
target: '#preview',
artifact,
});
await destroy(instance);

同一页面中所有顶层 create()、mount()、get()、destroy() 和 inspect() 都操作这个默认 Runtime。默认 Runtime 会复用底层 App 与资源生命周期,而每个 Instance 仍拥有自己的 id、props、节点映射和交互作用域。

target 与挂载时机

create({ artifact, target }) 会在创建 Instance 的同一步绑定目标,等价于调用默认 Runtime 的 mount(target, artifact)。如果没有 target、没有默认 canvas,Instance 不会自动附着到 DOM。

返回的 FlamoInstance 没有 mount(target) 方法,不能先无目标创建,再调用 instance.mount() 补挂载。需要 DOM/Canvas 宿主时,应在 create() 的选项中提供 target,或直接调用 mount()。

与 createFlamoRuntime() 的区别

API 创建什么 谁管理 Instance 适合场景
create(options) 一个 Instance 模块内置的默认 Runtime 单一预览、简单页面、无需自定义 Runtime 策略
createFlamoRuntime(options) 一个新的 Runtime 控制面 由你持有的 Runtime 编辑器、多画布、独立实例注册表、自定义资源池或宿主服务

如果只需要“把这个 Artifact 创建出来”,使用 create()。如果需要决定这些 Instance 与谁共享 App、由谁查询和销毁、使用哪个资源池,先调用 createFlamoRuntime(),再使用 runtime.create()。

const runtime = createFlamoRuntime({ canvas });
const instance = await runtime.create({ artifact });
runtime.get(instance.id); // 只查询这个 Runtime 的实例
await runtime.destroy(instance);

与 Card.create() 的区别

假设 Card 是 createFlamoComponentApi() 返回的组件 API:

const instance = await Card.create(props, options);

它会自动执行 Card(props) 生成 Artifact,并使用模块内置的默认 Runtime 创建 Instance。显式的 runtime.create() 不绑定某个组件 factory,调用方需要提供 Artifact 与运行态 props:

const artifact = Card(props);
const instance = await runtime.create({
...options,
artifact,
props,
});

因此,使用默认 Runtime 且希望少写样板代码时用 Card.create();需要指定 Runtime 的实例注册表、App、ResourcePool 或宿主服务时用 runtime.create()。

参数

options
FlamoCreateOptions
返回 Promise<FlamoInstance>来源 runtime/src/2d/framework/index.ts:10054
Function

mount

独立页面 ↗#

把 Artifact 挂载到目标元素,并返回默认 Runtime 创建的 Instance。

类型
mount(target: FlamoMountTarget, artifact: FlamoArtifact, options?: FlamoInstanceOptions): Promise<FlamoInstance>

这是最短的页面接入方式。顶层 mount() 使用模块内置的默认 Runtime;需要明确 Runtime 所有权、共享资源或多实例隔离时,使用 runtime.mount(target, artifact, options)。

import { mount } from '@flamo/runtime';
const instance = await mount('#preview', artifact);

mount(target, artifact, options) 会创建一个新 Instance,并在创建时绑定目标。它不是对已有 Instance 的二次挂载;FlamoInstance 没有 mount(target) 方法。

目标要求

  • selector 字符串在浏览器中通过 document.querySelector() 解析,找不到时抛出 flamo.mount: target not found;
  • HTMLCanvasElement 会直接作为渲染表面;
  • 其他 Element 会收到 Runtime 创建的子 <canvas>,容器应能接收子节点并具有可见尺寸;
  • Document、Window、ShadowRoot、null 不属于公开目标类型。

不要与以下接口混淆:Card.mount() 是 Component API 使用默认 Runtime 的便捷方法;instance.mountChild()、mountComposition()、mountSlot() 修改当前 Instance 内部的 child/composition/slot,不会重设顶层 DOM 目标。

参数

target
FlamoMountTarget
artifact
FlamoArtifact
options?
FlamoInstanceOptions
返回 Promise<FlamoInstance>来源 runtime/src/2d/framework/index.ts:10050
Interface

FlamoCreateOptions

独立页面 ↗#

创建 Instance 时同时指定 Artifact、目标、props、资源和宿主上下文。

类型
export interface FlamoCreateOptions

这是 runtime.create() 的完整选项。只有 artifact 是创建事实;target、canvas、host 和资源解析器属于本次运行环境。

target 接受 selector 字符串、Element 或 HTMLCanvasElement。它必须在创建 Instance 时提供;返回的 FlamoInstance 没有稍后补挂载的 mount(target) 方法。没有 target 时,Runtime 只会使用 appConfig.canvas 或 Runtime 默认 Canvas;两者也没有配置时,不会自动向 DOM 追加 Canvas。

返回 —来源 runtime/src/2d/framework/index.ts:2326
Interface

FlamoInstanceOptions

独立页面 ↗#

挂载 Artifact 时控制 Instance id、初始 props、宿主和运行策略。

类型
export interface FlamoInstanceOptions

它用于 runtime.mount() 的第三个参数,也构成 FlamoCreateOptions 除 artifact / target 外的公共部分。多个实例共存时请显式规划稳定且不冲突的 id;宿主与 canvas 仍是运行态资源。

target 不在这个接口中:调用 runtime.mount() 时它是第一个参数,调用 runtime.create() 时它属于扩展接口 FlamoCreateOptions。两种写法都在创建阶段绑定目标,不存在后续 instance.mount(target)。

返回 —来源 runtime/src/2d/framework/index.ts:2290
Interface

FlamoInstance

独立页面 ↗#

Artifact 在某个 Runtime 中运行后的可查询、可交互、可销毁对象。

类型
export interface FlamoInstance

Instance 持有 props、事件、方法、slot 和运行态引用。它只能在创建它的 JavaScript 进程与 Runtime 生命周期内使用。

需要等待 Variant 与普通绑定以一个事务完成时,使用 setProps();它返回 FlamoPropsCommitReceipt,失败或取消不会发布部分属性状态。

Instance 能否跨模块引用

可以。在同一个页面、同一个 JavaScript realm 和同一份模块图内,Instance 是普通活对象,可以由一个 TS/JS 模块导出引用,再由另一个模块导入使用。导出的不是副本或组件定义,导入方必须处理尚未创建、已经销毁和 owner teardown 等生命周期状态。

不能做的是把 Instance 保存为 JSON、写进 Artifact、通过 structured clone / Worker / iframe / 进程边界传递,或把它当作可再次实例化的 Component Release。跨环境恢复必须保存定义与输入,再创建新的 Instance。

需要持久化或传输时,请保存以下信息:

  • 用于创建它的 Artifact;
  • 或 Component 模块的稳定标识、版本和 props;
  • 如涉及创作变更,再保存明确的 authoring transaction。

恢复时重新导入 Artifact 或 Component,并在目标 Runtime 中再次调用 create() / mount():

const instance = await runtime.create({ artifact: importedArtifact });
// 当前生命周期结束时只销毁句柄;需要恢复的定义已另行保存
await runtime.destroy(instance);

Instance 没有宿主 mount()

宿主 DOM/Canvas 挂载属于 FlamoRuntime 或 FlamoComponentApi:

const instance = await runtime.mount('#preview', artifact);
// 或 runtime.create({ target: '#preview', artifact })

FlamoInstance 没有 mount(target)。它名称中带 mount 的方法操作的是当前实例内部:mountChild() 挂 child graph,mountComposition() 挂组合 IR,mountSlot() 分配 slot 内容;这些方法都不会把当前 Instance 重新绑定到另一个 DOM 目标。

父子 Instance 图

组合组件运行后,父 Instance 可以通过 children、child(key) 与 publicChild(key) 读取层级,也可以用 mountChild()、swapChild()、reconcileChildren() 临时修改当前运行树。

这些方法不会修改原始 Artifact,也不会生成新的 Component Release。需要把当前结构长期保存并封装为新组件时,应使用稳定 child key、精确 Component Ref、parentKey、mount、props、slots 和 routes 重建 Composition IR,再编译为新 Artifact。参见 组合多个组件并封装为新组件。

需要 API
保留现有 children,只新增一个 key mountChild()
声明完整目标列表并批量复用、新增、移除 reconcileChildren()
保留 key,替换该位置的 child 定义 swapChild()
返回 —来源 runtime/src/2d/framework/index.ts:2368
Interface

RuntimeInstanceGraphNode

独立页面 ↗#

Runtime 对父子 Instance 图中一个节点提供的只读快照。

类型
export interface RuntimeInstanceGraphNode

instance.children、instance.child(key) 与 instance.publicChild(key) 返回该快照,而不是可直接操作的 FlamoInstance 本体。

const node = panel.child('submit');
if (node) {
console.log(node.instanceId, node.lifecycleState, node.ownership);
const childInstance = runtime.get(node.instanceId);
childInstance?.set({ disabled: true });
}

children 字段保存直接后代的 Instance id。要遍历完整图,可从 runtime.get(id) 继续读取其 children,或使用 Inspector snapshot。不要修改快照字段;父子关系只能通过 composition transaction API 改变。

字段

childKey
string | null
children
readonly string[]
componentRef?
{ ... }
generation
number
instanceId
string
layout?
FlamoBoundaryLayoutSnapshot
lifecycleState
"mounted" | "disposed" | "preparing" | "disposing" | "failed"
logicalMount?
{ ... }
ownerBoundaryId
string
ownerCounts
Readonly<Record<RuntimeOwnerKind, number>>
ownership
"runtime" | "caller"
parentId
string | null
physicalMount?
{ ... }
返回 —来源 runtime/src/2d/framework/component/ComponentRuntimeGraph.ts:222
Function

get

独立页面 ↗#

通过 id 或宿主元素查询默认 Runtime 已登记的 Instance。

类型
get(idOrElement: string | Element): FlamoInstance | undefined

找不到目标时返回 undefined。自建 Runtime 的实例不在默认注册表中,应调用对应 Runtime 的 get()。

参数

idOrElement
string | Element
返回 FlamoInstance | undefined来源 runtime/src/2d/framework/index.ts:10058
Function

inspect

独立页面 ↗#

获取默认 Runtime 当前所有 Instance 的只读诊断快照。

类型
inspect(): FlamoInspectorSnapshot

适合调试和自动化证据采集。快照可能在下一帧变化;不要把它当作写入 API 或长期事实源。

返回 FlamoInspectorSnapshot来源 runtime/src/2d/framework/index.ts:10066
Interface

FlamoInspectorSnapshot

独立页面 ↗#

某一时刻 Runtime 中所有公开实例状态的只读检查快照。

类型
export interface FlamoInspectorSnapshot

用于 DevTools、Studio inspector 和自动化诊断。每个 FlamoInspectorInstanceSnapshot 还可提供 descendant ownership、Node Script disposer、listener、pending task/mutation、slot surface、resource reference、ECS entity 与 limbo component 计数,适合在销毁测试前后验证资源归零。快照不是 durable Artifact,也不能作为修改运行状态的命令接口。

返回 —来源 runtime/src/2d/framework/index.ts:1930
Interface

FlamoInspectorInstanceSnapshot

独立页面 ↗#

Public state and resource-lifecycle snapshot for one live Runtime instance.

类型
export interface FlamoInspectorInstanceSnapshot

字段

artifactId?
string
artifactName?
string
componentGraph?
RuntimeInstanceGraphNode
componentSetSelections?
Record<string, FlamoComponentSetSelection>
componentTransactions?
readonly RuntimeCompositionReceipt[]
id
string
lifecycle?
{ ... }

Live ownership and cleanup counters used to verify complete teardown.

nodeArtifacts?
Record<string, FlamoInspectorNodeArtifactSnapshot>
nodeScripts?
FlamoNodeScriptMountSnapshot[]
overrides
readonly FlamoOverride[]
props
Record<string, unknown>
publicApi
{ ... }
rootId?
string | null
runtimeScene?
unknown
slots
Record<string, unknown>
slotStates?
Record<string, FlamoSlotState>
wrapper
FlamoWrapperContract
返回 —来源 runtime/src/2d/framework/index.ts:1894
Interface

FlamoNodeScriptLifecycleSnapshot

独立页面 ↗#

Observable Node Script route, listener, exercise, and failure lifecycle.

类型
export interface FlamoNodeScriptLifecycleSnapshot

字段

cleanupStatus?
"disposed" | "not-registered" | "active"
entry?
string
error?
string
handlerError
{ ... } | null
importedAt?
number
inheritedFrom?
string
instanceId?
string
key
string
lastEventAt
number | null
lastTarget
string | null
lifecycle
FlamoNodeScriptLifecycleStage
listeners
string[]
listenerTargets
Record<string, string>

Legacy single-target projection retained for compatibility.

listenerTargetSets
Record<string, string[]>

Every distinct authoring/runtime target registered for each event.

mountedAt?
number
reason?
string
resolvedAt?
number
resolvedListenerTargets
Record<string, { ... }>
resolvedListenerTargetSets
Record<string, { ... }[]>
routeReady
boolean
runtimeNodeId?
string
scriptId?
string
sourceNodeId
string
status
FlamoNodeScriptMountStatus
updatedAt
number
返回 —来源 runtime/src/2d/framework/index.ts:1857
Interface

FlamoInteractionLifecycleSnapshot

独立页面 ↗#

Versioned interaction evidence emitted for local preview and build receipts.

类型
export interface FlamoInteractionLifecycleSnapshot

字段

eventRoutes
Record<string, unknown> | null
instanceId
string
nodeArtifacts
Record<string, FlamoInspectorNodeArtifactSnapshot>
nodeScripts
FlamoNodeScriptLifecycleSnapshot[]
runtimeAbi
{ ... }
schemaVersion
1
summary
Record<string, number>
trace
NodeScriptInteractionTraceEntry[]
返回 —来源 runtime/src/2d/framework/index.ts:1879
Function

destroy

独立页面 ↗#

通过 id、宿主元素或 Instance 销毁默认 Runtime 中的运行实例。

类型
destroy(idOrElementOrInstance: string | Element | FlamoInstance): Promise<boolean>

返回值表示是否找到并销毁了目标。使用自建 Runtime 时,应调用该 Runtime 自己的 destroy(target),避免跨隔离边界操作实例。

参数

idOrElementOrInstance
string | Element | FlamoInstance
返回 Promise<boolean>来源 runtime/src/2d/framework/index.ts:10062

动态组件与事务

动态组件与事务

Node Script 可从当前 Artifact export 或精确外部引用创建组件;创建、批量回滚、属性提交和销毁都受 Runtime 所有权与事务边界约束。

Method

FlamoInstance.setProps

独立页面 ↗#

以一次可取消、可回滚的事务原子提交 Instance 公共属性。

类型
FlamoInstance.setProps(patch: Record<string, unknown>, options?: { ... }): Promise<FlamoPropsCommitReceipt>

setProps() 会先验证完整 patch,并在每个 Instance 内串行执行。Variant 变更先完成,普通绑定与公共更新事件随后才可见;失败或取消会恢复之前的 selection,不发布部分 props。

当 Component Set 根脚本继承到页面中的具体 INSTANCE 时,ctx.instance.setProps() 会使用该脚本合并后的有效 surface,并自动把 Variant 绑定定向到当前实例。未知属性、无 Runtime binding 的属性和跨 Component Set 的绑定会返回 rejected;Variant 轴提交成功时,variantReceipts 至少包含当前实例的一条 applied 回执,不会再把页面级无绑定 patch 误报为成功。

const receipt = await instance.setProps({
disabled: false,
variant: { Size: 'Large', State: 'Active' },
}, { signal });
if (receipt.status !== 'committed') console.warn(receipt.error);

组件根脚本可以直接提交当前实例的状态轴:

const receipt = await ctx.instance.setProps({ state: 'hover' });
if (receipt.status !== 'committed' || receipt.variantReceipts[0]?.status !== 'applied') {
throw new Error(receipt.error?.message ?? 'Button state was not applied');
}

需要同步返回旧式链式句柄时可继续使用 set();需要等待最终一致状态、取消或审计时使用 setProps()。

参数

patch
Record<string, unknown>
options?
{ ... }
返回 Promise<FlamoPropsCommitReceipt>来源 runtime/src/2d/framework/index.ts:2411
Interface

FlamoPropsCommitReceipt

独立页面 ↗#

描述原子属性事务的提交、拒绝或取消结果。

类型
export interface FlamoPropsCommitReceipt

transactionId 可与 interaction trace 对齐;patch 是请求值的冻结副本;variantReceipts 保存同一事务内完成的 Variant commit。只有 status: 'committed' 表示完整 patch 已经对外可见,rejected 与 cancelled 都不会留下部分提交。

字段

error?
{ ... }

Structured failure information when status is rejected or cancelled.

patch
Readonly<Record<string, unknown>>

Frozen copy of the requested property patch.

status
"committed" | "rejected" | "cancelled"

Whether the complete patch committed, failed validation, or was cancelled.

transactionId
string

Stable id for correlating the mutation with Runtime traces.

variantReceipts
readonly FlamoVariantCommitReceipt[]

Variant transactions completed as part of the same atomic mutation.

返回 —来源 runtime/src/2d/framework/index.ts:2078
Method

FlamoInstance.mountChild

独立页面 ↗#

向当前父 Instance 的运行树新增一个具有稳定 key 的 child,并以 composition transaction 提交。

类型
FlamoInstance.mountChild(spec: RuntimeChildSpec, options?: ReconcileRuntimeChildrenOptions): Promise<RuntimeCompositionReceipt>

新增一个 child

mountChild() 保留现有 children,并在完整 desired set 中加入一个新的 RuntimeChildSpec。同一个父级不能重复使用相同 key。

这里的 mount 是“把 child 加入当前父 Instance 的运行图”,不是宿主 DOM 挂载。它不会改变父 Instance 的 target 或 canvas,也不是不存在的 instance.mount(target)。

const receipt = await panel.mountChild({
key: 'empty-state',
artifact: EmptyState({ message: '暂无结果' }),
parentKey: null,
mount: { kind: 'root' },
props: { compact: true },
statePolicy: 'preserve',
});
if (receipt.status !== 'committed') {
throw new Error(receipt.error?.message ?? `mountChild: ${receipt.status}`);
}
const child = panel.child('empty-state');

spec 必须且只能提供 ref、artifact、instance 其中一种:

  • ref:通过 Runtime 的 componentResolver 解析精确 Component Release;
  • artifact:创建 Runtime-owned 的本地 child;
  • instance:挂接已经存在的 live Instance,默认保持 caller-owned。

挂接 caller-owned Instance 时,父级销毁只会解除父子关系,不会替调用方销毁 child:

const preview = await runtime.create({ artifact: PreviewCard() });
await panel.mountChild({
key: 'preview',
instance: preview,
ownership: 'caller',
parentKey: null,
mount: { kind: 'root' },
});
await runtime.destroy(panel);
await runtime.destroy(preview); // 仍由调用方负责

该方法只修改当前 Runtime,不会写回 Artifact。需要保存层级时,应编译 Composition IR。

参数

spec
RuntimeChildSpec
options?
ReconcileRuntimeChildrenOptions
返回 Promise<RuntimeCompositionReceipt>来源 runtime/src/2d/framework/index.ts:2391
Method

FlamoInstance.reconcileChildren

独立页面 ↗#

用传入的完整列表更新父 Instance 下手动添加的子 Instance:可复用的保留,缺少的新增,未列出的移除;更新失败时全部恢复原状。

类型
FlamoInstance.reconcileChildren(specs: readonly RuntimeChildSpec[], options?: ReconcileRuntimeChildrenOptions): Promise<RuntimeCompositionReceipt>

声明完整目标树

reconcileChildren(specs) 接收的不是增量 patch,而是当前父 Instance 完整的手动 child 目标集合。未出现在新列表中的手动 child 会被移除;传入空数组会清空手动 children,Slot 运行时拥有的 child 不包含在这份列表中。

const specs = rows.map(row => ({
key: `row:${row.id}`,
ref: resultRowRef,
parentKey: null,
mount: { kind: 'root' },
props: { row, selected: row.id === selectedId },
statePolicy: 'preserve',
}));
const receipt = await resultList.reconcileChildren(specs, {
latestWins: true,
timeoutMs: 10_000,
});
if (receipt.status !== 'committed') {
console.error(receipt.error);
} else {
console.log('mounted', receipt.mounted);
console.log('reused', receipt.reused);
console.log('removed', receipt.removed);
}

构造嵌套层级

parentKey 引用同一份 specs 中另一个 child 的 key:

await panel.reconcileChildren([
{
key: 'toolbar',
artifact: Toolbar(),
parentKey: null,
mount: { kind: 'root' },
},
{
key: 'submit',
artifact: Button({ label: '提交' }),
parentKey: 'toolbar',
mount: { kind: 'slot', slotId: 'actions', outletId: 'primary' },
},
]);

协调规则:

  • key 必须在整份列表中唯一,parentKey 必须存在且不能形成循环;
  • 相同 key、相同 exact ref / Artifact object / Instance 且 statePolicy !== 'reset' 时复用原 child;上例使用 exact ref,因此重新生成 specs 不会破坏 row identity;
  • 默认 latest-wins,新 transaction 会 supersede 同一父级尚未提交的旧 transaction;
  • prepare 或 commit 失败时返回非 committed receipt,并恢复调用前的手动 child specs;
  • mounted、reused、removed 中记录的是 Instance id,不是 child key。

这是运行态协调接口。需要生成可持久化的新组件时,将相同 key / parentKey 结构写入 Composition IR。

参数

specs
readonly RuntimeChildSpec[]
options?
ReconcileRuntimeChildrenOptions
返回 Promise<RuntimeCompositionReceipt>来源 runtime/src/2d/framework/index.ts:2394
Method

FlamoInstance.swapChild

独立页面 ↗#

保留 child key 并替换其 ref、Artifact、Instance 或创建选项,然后重新协调父级运行树。

类型
FlamoInstance.swapChild(key: string, spec: Omit<RuntimeChildSpec, "key">, options?: ReconcileRuntimeChildrenOptions): Promise<RuntimeCompositionReceipt>

替换一个稳定位置

swapChild(key, spec) 的第二个参数不再包含 key。父级对该 key 的查询和 route 可以保持稳定,而实际 child 定义会被替换。

const receipt = await panel.swapChild('submit', {
artifact: DangerButton({ label: '删除' }),
parentKey: null,
mount: { kind: 'root' },
props: { disabled: false },
statePolicy: 'reset',
});
if (receipt.status === 'committed') {
console.log(panel.child('submit')?.instanceId);
}

使用相同 exact ref 或同一个 Artifact object 时,statePolicy: 'preserve' 可能复用现有 Instance 并只 patch props、slots 与 layout。需要强制重新创建时使用 statePolicy: 'reset'。

await panel.swapChild('submit', {
ref: nextButtonRef,
parentKey: null,
mount: { kind: 'root' },
props: { label: '继续' },
statePolicy: 'preserve',
}, {
signal: abortController.signal,
timeoutMs: 15_000,
});

如果 transaction 没有提交,swapChild() 会恢复调用前保存的 spec。与该 key 关联的其他 parentKey、公开引用和 route 无需改名;其嵌套 children 仍按完整 desired set 参与本次 reconcile。

该方法不会修改原始 Artifact,也不会发布新的 Component Release。

参数

key
string
spec
Omit<RuntimeChildSpec, "key">
options?
ReconcileRuntimeChildrenOptions
返回 Promise<RuntimeCompositionReceipt>来源 runtime/src/2d/framework/index.ts:2393
Interface

RuntimeChildSpec

独立页面 ↗#

描述一个运行时 child 的稳定身份、来源、父级、挂载位置、输入和所有权策略。

类型
export interface RuntimeChildSpec

三种 child 来源

每个 spec 必须且只能提供以下一种来源:

字段 用途 默认所有权
ref 精确 Component Ref,由 componentResolver 加载 Runtime-owned
artifact 已在当前进程取得的本地 Artifact Runtime-owned
instance 已经存在的 live Instance caller-owned

持久化 Composition IR 应优先保存带 hash 与 ABI 的 exact ref。artifact 适合本地运行组合;instance 只能用于当前 Runtime 生命周期,不能写入 Artifact。

key 在一次 reconcile 的完整列表中必须唯一。parentKey 负责父子所有权层级;mount 负责逻辑挂载位置。对于 artifact,Runtime 以对象 identity 判断是否可复用,而不是对 Artifact 做深比较。

mount 不是 DOM target

这里的 mount 类型是 FlamoMountPoint,描述 child 在父实例图中的逻辑位置:

  • { kind: 'root' }:挂到父 boundary 根;
  • { kind: 'node', nodeId }:挂到父级指定节点;
  • { kind: 'slot', slotId, outletId }:挂到指定 slot outlet;
  • { kind: 'portal', portalTarget }:逻辑 owner 仍是父实例,但物理位置由 portal target 决定。

它不同于 runtime.mount(target, artifact) 的 FlamoMountTarget,不会把 child 或父 Instance 重新绑定到浏览器 DOM 元素。

字段

artifact?
unknown

Runtime-local Artifact input. Durable graphs should prefer exact ref.

instance?
RuntimeComponentInstance
key
string
layout?
{ ... }
mount?
{ ... }
ownership?
"runtime" | "caller"
parentKey?
string | null
prepareRetries?
number
prepareTimeoutMs?
number
props?
Record<string, unknown>
ref?
{ ... }
serviceAllowlist?
readonly string[]
slots?
Record<string, unknown>
statePolicy?
"preserve" | "reset" | "migrate"
返回 —来源 runtime/src/2d/framework/component/ComponentRuntimeGraph.ts:185
Interface

ReconcileRuntimeChildrenOptions

独立页面 ↗#

控制 child graph transaction 的取消、超时、重试、并发取胜规则与变更回调。

类型
export interface ReconcileRuntimeChildrenOptions
  • signal:取消当前 transaction;返回状态通常为 cancelled。
  • timeoutMs:单个 child prepare 的默认超时时间。
  • retries:child prepare 失败后的默认重试次数。
  • latestWins:默认为 latest-wins;设为 false 时,同一父级已有活动 transaction 会拒绝新的协调。
  • onChildrenChanged:供 mountComposition() / hotUpdateComposition() 的 composition controller 在初始化或动态结构 commit 后报告最新 specs。直接调用 mountChild()、swapChild()、reconcileChildren() 时,应读取 receipt 和 instance.children,不要依赖该回调。

child spec 自己的 prepareTimeoutMs / prepareRetries 会覆盖这里的默认值。

字段

latestWins?
boolean
onChildrenChanged?
{ ... }
retries?
number
signal?
AbortSignal
timeoutMs?
number
返回 —来源 runtime/src/2d/framework/component/ComponentRuntimeGraph.ts:489
Interface

RuntimeCompositionReceipt

独立页面 ↗#

记录一次 child graph transaction 的最终状态以及新增、复用、移除的 Instance id。

类型
export interface RuntimeCompositionReceipt

调用方至少应检查 status,不能仅以 Promise fulfilled 判断提交成功:

const receipt = await panel.reconcileChildren(specs);
switch (receipt.status) {
case 'committed':
console.log('mounted', receipt.mounted);
console.log('reused', receipt.reused);
console.log('removed', receipt.removed);
break;
case 'cancelled':
case 'superseded':
case 'rolled_back':
case 'rejected':
console.error(receipt.error?.code, receipt.error?.message);
break;
}

mounted、reused、removed 都是 Instance id 数组。业务层需要稳定 child identity 时,继续使用传入的 RuntimeChildSpec.key 或 instance.child(key) 查询。

字段

error?
{ ... }
mounted
readonly string[]
parentId
string
removed
readonly string[]
reused
readonly string[]
status
"committed" | "rejected" | "cancelled" | "rolled_back" | "superseded"
transactionId
string
返回 —来源 runtime/src/2d/framework/component/ComponentRuntimeGraph.ts:253
Interface

NodeScriptComponentApi

独立页面 ↗#

Dynamic component creation surface available inside a Node Script.

类型
export interface NodeScriptComponentApi
返回 —来源 runtime/src/2d/framework/index.ts:2144
Method

NodeScriptComponentApi.create

独立页面 ↗#

从 owning Artifact export 或精确外部引用创建 parent-owned 组件。

类型
NodeScriptComponentApi.create(component: string | { ... }, options?: ComponentCreateOptions): Promise<ComponentInstanceHandle<TEvents>>

字符串只解析当前 owning Artifact 的 export 及其完整 definition closure;跨 Artifact 创建必须传完整的 FlamoComponentRefV1,并通过 revision、hash、Runtime ABI 与 component ABI 校验。

const badge = await ctx.components.create('Badge', {
parent: ctx.scene.root,
props: { label: 'New' },
placement: { kind: 'append' },
key: 'dynamic-badge',
signal,
});

准备、挂载或初始化失败时会回滚,不留下半挂载 entity。一个 owner 最多保留 1000 个动态 child。

参数

component
string | { ... }
options?
ComponentCreateOptions
返回 Promise<ComponentInstanceHandle<TEvents>>来源 runtime/src/2d/framework/index.ts:2146
Method

NodeScriptComponentApi.createBatch

独立页面 ↗#

批量创建最多 100 个组件,并在任一失败时逆序回滚。

类型
NodeScriptComponentApi.createBatch(requests: readonly ComponentCreateRequest[], options?: { ... }): Promise<readonly ComponentInstanceHandle<Record<string, unknown>>[]>

批量级 AbortSignal 应用于全部请求,单个 request 自己的 signal 优先。任何请求失败时,已经创建的实例会按逆序销毁,调用方不会观察到部分成功的结果。

const handles = await ctx.components.createBatch([
{ component: 'Avatar', props: { userId: 'a' } },
{ component: 'Avatar', props: { userId: 'b' } },
], { signal });

参数

requests
readonly ComponentCreateRequest[]
options?
{ ... }
返回 Promise<readonly ComponentInstanceHandle<Record<string, unknown>>[]>来源 runtime/src/2d/framework/index.ts:2151
Interface

ComponentCreateOptions

独立页面 ↗#

Options for NodeScriptComponentApi.create.

类型
export interface ComponentCreateOptions

字段

key?
string

Stable child key within the owning instance. Runtime creates one when omitted.

parent?
ComponentInstanceHandle<Record<string, unknown>> | RuntimeNode

Physical parent. Defaults to the current script boundary.

placement?
ComponentPlacement

Sibling-relative placement. Defaults to append.

props?
Record<string, unknown>

Initial public properties validated before the child becomes observable.

signal?
AbortSignal

Cancels preparation and rolls back any partially prepared child.

返回 —来源 runtime/src/2d/framework/index.ts:2107
Interface

ComponentCreateRequest

独立页面 ↗#

One entry accepted by NodeScriptComponentApi.createBatch.

类型
export interface ComponentCreateRequest

字段

component
string | { ... }

Owning-Artifact export name or an exact external component reference.

key?
string

Stable child key within the owning instance. Runtime creates one when omitted.

parent?
ComponentInstanceHandle<Record<string, unknown>> | RuntimeNode

Physical parent. Defaults to the current script boundary.

placement?
ComponentPlacement

Sibling-relative placement. Defaults to append.

props?
Record<string, unknown>

Initial public properties validated before the child becomes observable.

signal?
AbortSignal

Cancels preparation and rolls back any partially prepared child.

返回 —来源 runtime/src/2d/framework/index.ts:2121
Type alias

ComponentPlacement

独立页面 ↗#

Placement of a dynamically created component under its physical parent.

类型
export type ComponentPlacement
返回 —来源 runtime/src/2d/framework/index.ts:2100
Interface

ComponentInstanceHandle

独立页面 ↗#

控制一个动态 child 的属性、事件、检查与销毁生命周期。

类型
export interface ComponentInstanceHandle

ComponentInstanceHandle<TEvents> 属于一个 live child Instance:id 与 root 给出当前身份,setProps() 走原子属性事务,on() 返回幂等 disposer,inspect() 暴露公共状态与清理计数,destroy() 幂等释放当前实例和 parent-owned 后代。

句柄不能被序列化、写入 Artifact 或跨 realm 传递;需要恢复时应保存组件引用和输入,再创建新实例。

字段

id
string

Runtime instance id.

root
RuntimeNode

Live root node of this component instance.

返回 —来源 runtime/src/2d/framework/index.ts:2127
Method

ComponentInstanceHandle.setProps

独立页面 ↗#

Atomically validate and commit a public property patch.

类型
ComponentInstanceHandle.setProps(patch: Record<string, unknown>, options?: { ... }): Promise<FlamoPropsCommitReceipt>

参数

patch
Record<string, unknown>
options?
{ ... }
返回 Promise<FlamoPropsCommitReceipt>来源 runtime/src/2d/framework/index.ts:2133
Method

ComponentInstanceHandle.on

独立页面 ↗#

Subscribe to a typed business event and receive an idempotent disposer.

类型
ComponentInstanceHandle.on(event: K, handler: { ... }): { ... }

参数

event
K
handler
{ ... }
返回 { ... }来源 runtime/src/2d/framework/index.ts:2135
Method

ComponentInstanceHandle.inspect

独立页面 ↗#

Read the current public and lifecycle inspector snapshot.

类型
ComponentInstanceHandle.inspect(): FlamoInspectorInstanceSnapshot
返回 FlamoInspectorInstanceSnapshot来源 runtime/src/2d/framework/index.ts:2138
Method

ComponentInstanceHandle.destroy

独立页面 ↗#

Idempotently destroy this instance and every parent-owned descendant.

类型
ComponentInstanceHandle.destroy(): Promise<void>
返回 Promise<void>来源 runtime/src/2d/framework/index.ts:2140
Interface

NodeScriptSelfApi

独立页面 ↗#

Identity and lifecycle surface for the Node Script's owning FlamoInstance.

类型
export interface NodeScriptSelfApi

字段

id
string

Owning FlamoInstance id; this is not necessarily the current mounted node id.

root
RuntimeNode

Live root node of the whole owning FlamoInstance.

返回 —来源 runtime/src/2d/framework/index.ts:2155
Method

NodeScriptSelfApi.destroy

独立页面 ↗#

从 Node Script 内幂等销毁 owning Instance 及其所有权子树。

类型
NodeScriptSelfApi.destroy(): Promise<void>

await ctx.self.destroy() 会递归释放 parent-owned descendants、listeners、scheduled tasks、HTML surfaces、pointer captures 与资源引用。重复调用不会重复 teardown;销毁开始后不要再排入新的 mutation。

返回 Promise<void>来源 runtime/src/2d/framework/index.ts:2164

场景与节点查询

场景与节点查询

从 Instance 或 Node Script 的 scene 控制面查询稳定语义树;按名查询保留重复节点,并始终用数组表达零个、一个或多个结果。

Interface

SceneApi

独立页面 ↗#

Instance-scoped control surface for querying and mutating the semantic scene. Mounted ECS clones are intentionally excluded. Node Scripts that need the current physical materialization use `ctx.mounted` instead.

类型
export interface SceneApi
返回 —来源 runtime/src/2d/scene/types.ts:435
Method

SceneApi.findByName

独立页面 ↗#

在指定语义 Scene 范围内按精确节点名查找全部稳定节点,并始终返回 RuntimeNode 数组。

类型
SceneApi.findByName(name: string, options?: SceneNameQueryOptions): RuntimeNode[]

查询区分大小写,保留重复名字,并按确定性的语义场景树顺序返回。没有匹配或 scope 无法解析时返回 [],不会返回 null。

const icons = ctx.scene.findByName('tag-close-icon', {
scope: ctx.nodeId,
});

省略 scope 时从当前 Scene 根查询;scope 可以是节点 ID、RuntimeNode,或当前 Flamo Instance 内的 'global'。结果只包含 Artifact、instance-scoped 和 Scene 创建节点,不会遍历或返回当前 ECS clone。需要当前 Slot/Variant 的物理内容时使用 ctx.mounted;如果目标只用于响应事件,优先使用 ctx.delegate(),它会把动态查询与 canonical 事件路径匹配起来。

参数

name
string
options?
SceneNameQueryOptions
返回 RuntimeNode[]来源 runtime/src/2d/scene/types.ts:446
Interface

SceneNameQueryOptions

独立页面 ↗#

Controls the scene subtree searched by SceneApi.findByName.

类型
export interface SceneNameQueryOptions

字段

scope?
NodeRef

Root node of the search. Omit it to search the owning scene root, or use `global` to search every root owned by the current Flamo instance.

返回 —来源 runtime/src/2d/scene/types.ts:421
Interface

RuntimeNode

独立页面 ↗#

Live handle for one node in the owning Flamo instance scene graph.

类型
export interface RuntimeNode
返回 —来源 runtime/src/2d/scene/types.ts:361
Method

RuntimeNode.on

独立页面 ↗#

在一个已解析的 RuntimeNode 上直接监听统一事件。

类型
RuntimeNode.on(event: UnifiedEventType, handler: UnifiedEventHandler, options?: EventListenerOptions): { ... }

适合宿主代码先通过 instance.scene.get()、queryAll() 或 findByName() 获得 live node handle 后绑定事件。返回的函数用于注销监听,Instance 销毁后 handle 不应继续复用。

Node Script 内优先使用 ctx.onNode() 或 ctx.delegate(),以获得脚本生命周期清理、role 解析和动态命名节点语义。

参数

event
UnifiedEventType
handler
UnifiedEventHandler
options?
EventListenerOptions
返回 { ... }来源 runtime/src/2d/scene/types.ts:390
Method

RuntimeNode.emit

独立页面 ↗#

Flamo Runtime 的公开类型与调用合同。

类型
RuntimeNode.emit(event: string, payload?: unknown): void

参数

event
string
payload?
unknown
返回 void来源 runtime/src/2d/scene/types.ts:391
Type alias

NodeRef

独立页面 ↗#

Any stable node reference accepted by the scene API. Entity handles returned by node-script helpers such as `ctx.role()` expose an `id` but are intentionally not `RuntimeNode` instances. Accepting the small structural contract keeps the documented `ctx.scene.mount(node, { parent: ctx.role('body') })` form type-safe.

类型
export type NodeRef
返回 —来源 runtime/src/2d/scene/types.ts:117
Interface

UnifiedEvent

独立页面 ↗#

RuntimeNode 与事件桥接层使用的跨 Canvas、HTML Surface 和平台输入统一事件对象。

类型
export interface UnifiedEvent

该对象使用 canonical Runtime entity id 表达 target、currentTarget 和 composedPath(),并统一坐标、修饰键、pointer、wheel、keyboard、drag、gesture 与 DOM 输入字段。

组件 Node Script 通常通过 NodeScriptEventMap 获得更精确的事件类型;只有宿主直接使用 RuntimeNode.on() 或编写平台适配时才需要面向 UnifiedEvent。

返回 —来源 runtime/src/2d/framework/binding/EventBridge.ts:66
Type alias

UnifiedEventHandler

独立页面 ↗#

事件处理器

类型
export type UnifiedEventHandler
返回 —来源 runtime/src/2d/framework/binding/EventBridge.ts:157
Type alias

UnifiedEventType

独立页面 ↗#

统一事件类型(跨平台)- 扩展 FlamoEventType 以支持更多平台事件

类型
export type UnifiedEventType
返回 —来源 runtime/src/2d/framework/binding/EventBridge.ts:58

Mounted 实体与连续交互

Mounted 实体与连续交互

显式读取当前物理挂载实体、live probe 和 direct children,并按帧批量提交位置;这些瞬时 handle 不进入 Artifact 或语义查询。

身份域

语义树用于查找,Mounted 树用于当前物理实体

ctx.scene 始终返回 Artifact 节点、instance-scoped 引用和 Scene 创建节点组成的稳定语义树。 Variant、Slot 或重挂载产生的当前 ECS 实体通过 ctx.mounted.resolve/children/probe 显式读取。

mounted handle 只在当前 materialization 与 revision 内有效,不能持久化或解析其 id。 连续拖动时在 pointerdown 解析一次,并通过 ctx.setTransformsBatch() 每帧提交一批位置。

查看语义 Scene Tree 与 Mounted Entity Tree 的完整边界 →

Type alias

NodeScriptMountedRef

独立页面 ↗#

Semantic role/ref or an already-resolved mounted handle.

类型
export type NodeScriptMountedRef
返回 —来源 runtime/src/2d/framework/index.ts:1616
Interface

NodeScriptMountedNodeSnapshot

独立页面 ↗#

One entity in the current mounted ECS tree, paired with semantic identity when available.

类型
export interface NodeScriptMountedNodeSnapshot

字段

entity
EntityHandle

Opaque handle for the current physical entity.

instanceRootId
string | null

Owning semantic instance root for an instance-scoped reference.

revision
number

Scene mutation revision at which this snapshot was resolved.

semanticRef
string | null

Preferred stable semantic reference, when Runtime can recover one.

snapshot
NodeProbeSnapshot | null

Live geometry and visibility probe captured at `revision`.

sourceNodeId
string | null

Authoring source node id, when the entity comes from Artifact materialization.

返回 —来源 runtime/src/2d/framework/index.ts:1619
Interface

NodeScriptMountedChildrenSnapshot

独立页面 ↗#

Direct mounted children of one currently materialized parent entity.

类型
export interface NodeScriptMountedChildrenSnapshot

字段

children
readonly NodeScriptMountedNodeSnapshot[]

Direct physical children in current ECS relation order.

parent
NodeScriptMountedNodeSnapshot

Resolved mounted parent.

revision
number

Scene mutation revision shared by parent and children.

返回 —来源 runtime/src/2d/framework/index.ts:1635
Interface

NodeScriptMountedContentSnapshot

独立页面 ↗#

Flamo Runtime 的公开类型与调用合同。

类型
export interface NodeScriptMountedContentSnapshot

字段

contents
readonly EntityHandle[]

Current direct physical children in ECS relation order.

contentSnapshots
readonly NodeProbeSnapshot | null[]

Live probes aligned by index with `contents`.

primary
EntityHandle | null

First current direct child, retained for compatibility.

primarySnapshot
NodeProbeSnapshot | null

Live probe for `primary`, when one exists.

revision
number

Scene mutation revision shared by every field in this snapshot.

viewport
EntityHandle

Current physical viewport handle. Do not persist or parse its id.

viewportSnapshot
NodeProbeSnapshot | null

Live probe captured for the viewport at `revision`.

返回 —来源 runtime/src/2d/framework/index.ts:1598
Interface

NodeScriptMountedApi

独立页面 ↗#

Explicit read boundary for the current physical ECS materialization.

类型
export interface NodeScriptMountedApi
返回 —来源 runtime/src/2d/framework/index.ts:1645
Method

NodeScriptMountedApi.resolve

独立页面 ↗#

Resolve a semantic role/ref or mounted handle to the current physical entity.

类型
NodeScriptMountedApi.resolve(ref: NodeScriptMountedRef): NodeScriptMountedNodeSnapshot | null

参数

ref
NodeScriptMountedRef
返回 NodeScriptMountedNodeSnapshot | null来源 runtime/src/2d/framework/index.ts:1647
Method

NodeScriptMountedApi.children

独立页面 ↗#

读取一个当前 mounted parent 及其 direct physical children 的同 revision 快照。

类型
NodeScriptMountedApi.children(ref: NodeScriptMountedRef): NodeScriptMountedChildrenSnapshot | null

该方法按 ECS relation order 返回当前 direct children,不递归搜索名称,也不会改变 ctx.scene 的语义层级。它适合 Scroll viewport、Slot 当前内容和 Variant 的实时物理测量。

返回 null 表示 ref 当前无法 materialize/resolve;返回空 children 表示 parent 已解析但没有可探测的 direct child。缓存结果时同时保存 revision,scene revision 变化后重新读取。

参数

ref
NodeScriptMountedRef
返回 NodeScriptMountedChildrenSnapshot | null来源 runtime/src/2d/framework/index.ts:1649
Method

NodeScriptMountedApi.probe

独立页面 ↗#

Read the current live probe for the resolved physical entity.

类型
NodeScriptMountedApi.probe(ref: NodeScriptMountedRef): NodeProbeSnapshot | null

参数

ref
NodeScriptMountedRef
返回 NodeProbeSnapshot | null来源 runtime/src/2d/framework/index.ts:1651
Property

NodeScriptContext.mounted

独立页面 ↗#

显式读取当前 ECS 物理挂载实体;SceneApi 继续只负责稳定语义树。

类型
export const NodeScriptContext.mounted: NodeScriptMountedApi

使用 resolve(ref) 取得当前 canonical mounted entity,使用 children(ref) 读取 direct physical children,使用 probe(ref) 读取 live geometry/visibility。ref 可以是 role、semantic ref 或已有 mounted handle。

返回 snapshot 的 revision 用于判断缓存是否过期。Variant、Slot 或 rematerialization 改变 revision 后重新解析;不要持久化或按字符串格式解析 entity.id。

const tree = ctx.mounted.children('viewport');
if (!tree) return;
for (const child of tree.children) {
ctx.trace('mounted-child', {
semanticRef: child.semanticRef,
revision: child.revision,
});
}

按名称、role 或组件语义查询仍使用 ctx.scene。两棵树的完整区别见语义 Scene Tree 与 Mounted Entity Tree。

返回 —来源 runtime/src/2d/framework/index.ts:2204
Method

NodeScriptContext.eventPoint

独立页面 ↗#

Convert a Flamo event world coordinate into the current node or target node's live local coordinates.

类型
NodeScriptContext.eventPoint(event: BaseFlamoEvent, ref?: string): { ... } | null

参数

event
BaseFlamoEvent
ref?
string
返回 { ... } | null来源 runtime/src/2d/framework/index.ts:2238
Method

NodeScriptContext.mountedContent

独立页面 ↗#

兼容旧 Scroll 脚本的 mounted children 投影;新代码使用 ctx.mounted.children()。

类型
NodeScriptContext.mountedContent(ref: string): NodeScriptMountedContentSnapshot | null

该方法保留 viewport / contents / primary / snapshots / revision 结构,只读取当前 direct physical children。它不会通过 SceneApi 搜索 mounted clone,也不允许调用方持久化 physical id。

新脚本使用 ctx.mounted.children(ref),以统一的 mounted node snapshot 读取 semantic ref、source、instance、live probe 和 revision。

参数

ref
string
返回 NodeScriptMountedContentSnapshot | null来源 runtime/src/2d/framework/index.ts:2240
Interface

NodeScriptTransformBatchUpdate

独立页面 ↗#

One position write in a frame-coalesced mounted transform batch.

类型
export interface NodeScriptTransformBatchUpdate

字段

ref
string | EntityHandle

Semantic role/ref or mounted handle resolved inside the owning SceneRuntime.

x
number

Parent-local x position.

y
number

Parent-local y position.

返回 —来源 runtime/src/2d/framework/index.ts:1655
Interface

NodeScriptTransformBatchReceipt

独立页面 ↗#

Result of accepting one mounted transform batch into the fast channel.

类型
export interface NodeScriptTransformBatchReceipt

字段

accepted
readonly string[]

Resolved entity ids accepted by the batch.

missing
readonly string[]

Input refs that could not be resolved or contained non-finite coordinates.

返回 —来源 runtime/src/2d/framework/index.ts:1665
Method

NodeScriptContext.setTransformsBatch

独立页面 ↗#

在 owning SceneRuntime 的 fast channel 中合并一帧的位置写入,并返回 accepted/missing refs。

类型
NodeScriptContext.setTransformsBatch(updates: readonly NodeScriptTransformBatchUpdate[]): NodeScriptTransformBatchReceipt

用于 Scroll、Slider、拖拽面板等连续交互,把 content 与 thumb 的位置放在同一批中提交。每个 animation frame 最多调用一次;Runtime flush 后只发布一次 scene mutation revision,使 renderer 与 picker 观察同一几何状态。

const receipt = ctx.setTransformsBatch([
{ ref: content.entity, x: contentX, y: contentY },
{ ref: 'vertical-thumb', x: thumbX, y: thumbY },
]);
if (receipt.missing.length > 0) {
ctx.trace('scroll.targets.missing', receipt.missing);
}

accepted 表示已经进入 fast channel,不表示已经渲染;需要读取提交后的状态时等待下一帧并重新 probe。

参数

updates
readonly NodeScriptTransformBatchUpdate[]
返回 NodeScriptTransformBatchReceipt来源 runtime/src/2d/framework/index.ts:2253
Interface

EntityHandle

独立页面 ↗#

实体句柄(高频操作用)

类型
export interface EntityHandle

字段

children?
EntityHandle[]

获取子节点

id
string
name?
string
parent?
EntityHandle

获取父节点

transform
{ ... }
返回 —来源 runtime/src/2d/framework/types.ts:162
Method

EntityHandle.setInteractive

独立页面 ↗#

配置节点的权威交互模式、pointer policy、透明命中面、cursor 与 z-index。

类型
EntityHandle.setInteractive(value: { ... }): void

mode: 'disabled'、inert 和 pointerEvents: 'none' 是更强的禁用规则。box-only 只允许当前节点命中,box-none 只允许后代命中。

自动隐藏的 scrollbar gutter 可以在 paint opacity 为 0 时继续作为显式命中面:

gutter.setInteractive({
mode: 'enabled',
pointerEvents: 'box-only',
hitTestWhenTransparent: true,
cursor: 'pointer',
});

hitTestWhenTransparent 不会让 visible: false 的节点恢复交互;它只解除 paint opacity 与 hit-test membership 的隐式绑定。

参数

value
{ ... }
返回 void来源 runtime/src/2d/framework/types.ts:208

脚本与事件

脚本与事件

Node Script 只声明监听、代理和业务事件;命中测试、动态 clone、目标链、传播、坐标与输入事务由 Runtime 统一负责。

使用边界

脚本声明语义,Runtime 负责命中与传播

组件脚本使用 ctx.on()、ctx.onNode() 或 ctx.delegate() 订阅事件; 不需要读取包围盒、pick color、clone id,也不需要手工遍历父节点。按节点名查找使用instance.scene.findByName() 或 ctx.scene.findByName(),结果始终为数组。

event.target 是本次派发中稳定的 canonical Runtime entity id,currentTarget 与 phase 随 capture / target / bubble 更新;composedPath() 返回从目标到当前 Instance 根的完整 ID 路径。

查看事件、节点代理、Interact 开关和常见事件的完整教程 →

Function

defineNodeScript

独立页面 ↗#

定义由 Runtime 挂载并随节点生命周期自动清理的 Node Script。

类型
defineNodeScript(config: DefineNodeScriptConfig<Props>): NodeScriptDefinition<Props>

setup(props, ctx) 与 Vue 3 使用相同的参数顺序,并对普通 Component、Component Set 和普通图形节点统一有效。第一个参数是当前具体 FlamoInstance 的只读响应式输入;Component Set 继承脚本会收到当前 concrete INSTANCE 的有效 surface 与 Variant 参数。第二个参数负责状态、监听、节点访问、代理和公开方法。

节点的 x / y / fill / opacity / text 等视觉字段不会自动进入 props。普通图形不消费实例输入时使用 _props,通过 ctx.node().design() / current() 读取节点,通过语义 setter 或动画 API 修改节点。defineNodeScript<Props> 只增加 TypeScript 类型检查,不会创建 Artifact public surface。

export default defineNodeScript({
setup(props, ctx) {
ctx.on('click', event => {
ctx.emit('onClick', { targetNodeId: event.target, disabled: props.disabled });
});
},
});

普通图形脚本:

export default defineNodeScript({
setup(_props, ctx) {
const shape = ctx.node();
if (!shape) return;
const initialOpacity = shape.design().compositing.opacity;
ctx.on('pointerenter', () => shape.setOpacity(0.7));
ctx.on('pointerleave', () => shape.setOpacity(initialOpacity));
},
});

通过 ctx.on()、ctx.onNode()、ctx.delegate()、ctx.dispose() 登记的资源都属于当前 Instance 生命周期;脚本不需要自行管理 ECS、命中缓冲或 runtime clone。完整概念见脚本,事件工作流见事件、节点查询与动态代理。

参数

config
DefineNodeScriptConfig<Props>
返回 NodeScriptDefinition<Props>来源 runtime/src/2d/framework/index.ts:4575
Interface

DefineNodeScriptConfig

独立页面 ↗#

Author input accepted by defineNodeScript.

类型
export interface DefineNodeScriptConfig

字段

setup
NodeScriptSetup<Props>
surface?
FlamoArtifactControlSurface
返回 —来源 runtime/src/2d/framework/index.ts:1952
Interface

NodeScriptDefinition

独立页面 ↗#

Normalized, mountable Node Script definition.

类型
export interface NodeScriptDefinition
返回 —来源 runtime/src/2d/framework/index.ts:1959
Interface

NodeScriptContext

独立页面 ↗#

Lifecycle-owned authoring and interaction context passed to a Node Script.

类型
export interface NodeScriptContext
返回 —来源 runtime/src/2d/framework/index.ts:2182
Method

NodeScriptContext.on

独立页面 ↗#

在当前脚本根上监听统一事件,并参与 Runtime 的 capture、target、bubble 传播。

类型
NodeScriptContext.on(event: K, handler: { ... }, options?: EventListenerOptions): { ... }

默认监听 at-target 与 bubble 阶段,因此后代事件可以冒泡到组件根。pointerenter / pointerleave 不冒泡;需要监听稳定内部节点时使用 ctx.onNode(),按动态节点名匹配时使用 ctx.delegate()。

返回值是显式取消函数;即使不手动调用,Runtime 也会在脚本释放时清理监听。

参数

event
K
handler
{ ... }
options?
EventListenerOptions
返回 { ... }来源 runtime/src/2d/framework/index.ts:2224
Method

NodeScriptContext.onNode

独立页面 ↗#

把统一事件监听直接绑定到当前脚本作用域内的稳定 role 或节点引用。

类型
NodeScriptContext.onNode(ref: string, event: K, handler: { ... }, options?: EventListenerOptions): { ... }

ref 优先解析 Artifact 中声明的 role,也可以是当前 Scene 能解析的节点引用。它适合语义稳定且基数明确的内部节点;variant 中可能动态出现、消失或重复的命名节点应使用 ctx.delegate()。

注册监听不会把显式 interactive: false 或 mode: 'disabled' 改回可交互。

参数

ref
string
event
K
handler
{ ... }
options?
EventListenerOptions
返回 { ... }来源 runtime/src/2d/framework/index.ts:2227
Method

NodeScriptContext.onChild

独立页面 ↗#

直接监听当前同名后代,并在节点被替换后由 Runtime 自动重绑。

类型
NodeScriptContext.onChild(event: K, query: NodeScriptEventDelegate, handler: { ... }, options?: EventListenerOptions): { ... }

onChild() 适合确实需要逐元素直接监听语义的动态后代,包括 pointerenter、pointerleave、focus 与 blur。Runtime 会在 Variant、组件属性或 Artifact rematerialization 后刷新 exact-name 结果和 listener,不会继续依赖已经被替换的元素。

ctx.onChild('pointerenter', { name: 'tag-close-icon' }, event => {
ctx.emit('onCloseHover', { targetNodeId: event.target });
});

默认优先考虑 ctx.delegate():冒泡事件走 canonical 路径,非冒泡事件走稳定祖先捕获,通常具有更低的绑定维护成本。

参数

event
K
query
NodeScriptEventDelegate
handler
{ ... }
options?
EventListenerOptions
返回 { ... }来源 runtime/src/2d/framework/index.ts:2230
Method

NodeScriptContext.delegate

独立页面 ↗#

按精确节点名把事件代理给动态后代,非冒泡事件使用稳定祖先捕获。

类型
NodeScriptContext.delegate(event: K, query: NodeScriptEventDelegate, handler: { ... }, options?: EventListenerOptions): { ... }

Runtime 在每次事件发生时重新执行节点名查询,并把所有当前匹配与 canonical composedPath() 比较。variant 切换后目标暂时不存在是正常的空匹配;重复同名节点不会让同一次事件重复调用 handler。

ctx.delegate('click', { name: 'tag-close-icon' }, event => {
ctx.emit('onClose', { targetNodeId: event.target });
});

用户脚本不应为此读取包围盒、pick color、clone id 或手工遍历父链。省略 scope 时限制在当前脚本边界,只有明确需要时才扩大到当前 Instance 的 'global' 范围。

pointerenter/leave、focus/blur 等非冒泡事件不会退化为一次性元素绑定。Runtime 在稳定祖先的捕获阶段代理,并在事件到达时匹配当前 canonical 路径,所以 variant 替换目标元素后监听仍然有效。只有必须保持直接监听语义时才改用会自动重绑的 ctx.onChild()。

参数

event
K
query
NodeScriptEventDelegate
handler
{ ... }
options?
EventListenerOptions
返回 { ... }来源 runtime/src/2d/framework/index.ts:2233
Method

NodeScriptContext.onActivate

独立页面 ↗#

用同一个入口处理 click、Enter 与 Space 激活。

类型
NodeScriptContext.onActivate(ref: string | undefined, handler: { ... }, options?: NodeScriptActivationOptions): { ... }

onActivate() 忽略重复 keydown,并让指针与键盘共享同一个 disabled 判断。Enter/Space 默认阻止平台默认行为;只有宿主确实需要保留默认动作时才设置 preventDefault: false。

export default defineNodeScript({
setup(props, ctx) {
ctx.onActivate('submit-button', () => ctx.emit('submit'), {
disabled: () => Boolean(props.disabled),
});
},
});

参数

ref
string | undefined
handler
{ ... }
options?
NodeScriptActivationOptions
返回 { ... }来源 runtime/src/2d/framework/index.ts:2236
Method

NodeScriptContext.emit

独立页面 ↗#

从当前节点脚本发出一个组件或节点级业务事件。

类型
NodeScriptContext.emit(event: string, payload?: T): void

emit() 用于把输入事件转换为组件 surface 中声明的业务语义,例如 onClick、onClose 或 submit。payload 应保持可验证、可序列化,不要暴露 ECS 对象、DOM 对象或短生命周期 clone handle。

它不会伪造 pointer 命中或重新派发原生输入;输入目标、传播与默认行为仍由 Runtime 事件系统负责。

参数

event
string
payload?
T
返回 void来源 runtime/src/2d/framework/index.ts:2244
Interface

NodeScriptActivationOptions

独立页面 ↗#

Shared pointer and keyboard policy for NodeScriptContext.onActivate.

类型
export interface NodeScriptActivationOptions

字段

disabled?
boolean | { ... }

Static or reactive guard applied equally to pointer and keyboard activation.

preventDefault?
boolean

Prevent Enter/Space platform defaults unless explicitly false.

返回 —来源 runtime/src/2d/framework/index.ts:2168
Interface

NodeScriptEventDelegate

独立页面 ↗#

Exact-name query used by NodeScriptContext.delegate.

类型
export interface NodeScriptEventDelegate

字段

name
string

Exact Figma/Flamo node name. Every current match is considered.

scope?
NodeRef

Defaults to the current script boundary; use global only deliberately.

返回 —来源 runtime/src/2d/framework/index.ts:2092
Interface

NodeScriptEventMap

独立页面 ↗#

Strongly typed event-name to payload map used by NodeScriptContext listeners.

类型
export interface NodeScriptEventMap

字段

beforeinput
NodeScriptEvent<FlamoDomEvent>
blur
NodeScriptEvent<FlamoFocusEvent>
change
NodeScriptEvent<FlamoDomEvent>
click
NodeScriptEvent<FlamoClickEvent>
compositionend
NodeScriptEvent<FlamoDomEvent>
compositionstart
NodeScriptEvent<FlamoDomEvent>
compositionupdate
NodeScriptEvent<FlamoDomEvent>
contextmenu
NodeScriptEvent<FlamoClickEvent>
copy
NodeScriptEvent<FlamoDomEvent>
cut
NodeScriptEvent<FlamoDomEvent>
doubleclick
NodeScriptEvent<FlamoClickEvent>
drag
NodeScriptEvent<FlamoDragEvent>
dragend
NodeScriptEvent<FlamoDragEvent>
dragstart
NodeScriptEvent<FlamoDragEvent>
focus
NodeScriptEvent<FlamoFocusEvent>
focusin
NodeScriptEvent<FlamoFocusEvent>
focusout
NodeScriptEvent<FlamoFocusEvent>
gotpointercapture
NodeScriptEvent<FlamoPointerEvent>
input
NodeScriptEvent<FlamoDomEvent>
keydown
NodeScriptEvent<FlamoKeyboardEvent>
keyup
NodeScriptEvent<FlamoKeyboardEvent>
longpress
NodeScriptEvent<FlamoGestureEvent>
lostpointercapture
NodeScriptEvent<FlamoPointerEvent>
pan
NodeScriptEvent<FlamoGestureEvent>
panend
NodeScriptEvent<FlamoGestureEvent>
panstart
NodeScriptEvent<FlamoGestureEvent>
paste
NodeScriptEvent<FlamoDomEvent>
pinch
NodeScriptEvent<FlamoGestureEvent>
pinchend
NodeScriptEvent<FlamoGestureEvent>
pinchstart
NodeScriptEvent<FlamoGestureEvent>
pointercancel
NodeScriptEvent<FlamoPointerEvent>
pointerdown
NodeScriptEvent<FlamoPointerEvent>
pointerenter
NodeScriptEvent<FlamoPointerEvent>
pointerleave
NodeScriptEvent<FlamoPointerEvent>
pointermove
NodeScriptEvent<FlamoPointerEvent>
pointerout
NodeScriptEvent<FlamoPointerEvent>
pointerover
NodeScriptEvent<FlamoPointerEvent>
pointerup
NodeScriptEvent<FlamoPointerEvent>
rotate
NodeScriptEvent<FlamoGestureEvent>
rotateend
NodeScriptEvent<FlamoGestureEvent>
rotatestart
NodeScriptEvent<FlamoGestureEvent>
tap
NodeScriptEvent<FlamoGestureEvent>
wheel
NodeScriptEvent<FlamoWheelEvent>
返回 —来源 runtime/src/2d/framework/index.ts:1995
Type alias

NodeScriptEvent

独立页面 ↗#

Node Script 收到的统一事件投影,使用 canonical Runtime entity id 表达目标和传播路径。

类型
export type NodeScriptEvent

target 在一次派发中保持稳定;同一个 pointer transaction 的逻辑目标 identity 也不会因 Variant rematerialization 改变。currentTarget 和 phase 随 capture / target / bubble 更新;composedPath() 返回从实际目标到当前 Instance 根的 ID 数组。coordinates 同时提供 screen、view、world 与可用时的 local 坐标。

事件族的附加字段由 NodeScriptEventMap 决定:pointer 有 pointer,wheel 有 delta,keyboard 有 key/code,gesture 有 delta/scale/rotation,HTML Surface 输入包含 data、value 或 clipboardData。

返回 —来源 runtime/src/2d/framework/index.ts:1987
Interface

EventListenerOptions

独立页面 ↗#

配置统一事件监听器的捕获阶段、单次执行和被动默认行为语义。

类型
export interface EventListenerOptions
  • capture: true:在事件到达目标前的捕获阶段执行。
  • once: true:第一次执行后自动注销。
  • passive: true:声明 handler 不会取消平台默认行为;此时 preventDefault() 不生效。

消费 wheel、触控板或浏览器默认行为的监听器不能声明为 passive。stopPropagation() 与 stopImmediatePropagation() 属于事件对象,不属于 listener options。

字段

capture?
boolean

是否在捕获阶段触发

once?
boolean

是否只触发一次

passive?
boolean

是否为被动监听器

返回 —来源 runtime/src/2d/framework/binding/EventBridge.ts:173
Type alias

EventType

独立页面 ↗#

Event names emitted by the canonical Flamo event route.

类型
export type EventType
返回 —来源 runtime/src/2d/utils/events/types.ts:6
Interface

BaseFlamoEvent

独立页面 ↗#

Shared event payload before a concrete event family adds pointer, wheel, keyboard, drag, gesture, or DOM-specific data. Node scripts receive a NodeScriptEvent projection whose target, currentTarget, and composed path are canonical Runtime entity IDs.

类型
export interface BaseFlamoEvent
返回 —来源 runtime/src/2d/utils/events/types.ts:58
Type alias

FlamoEvent

独立页面 ↗#

Union of every typed Flamo event family.

类型
export type FlamoEvent
返回 —来源 runtime/src/2d/utils/events/types.ts:152
Interface

FlamoPointerEvent

独立页面 ↗#

Pointer input, pointer boundary, and pointer-capture event payload.

类型
export interface FlamoPointerEvent
返回 —来源 runtime/src/2d/utils/events/types.ts:78
Interface

FlamoWheelEvent

独立页面 ↗#

Wheel or trackpad delta payload.

类型
export interface FlamoWheelEvent
返回 —来源 runtime/src/2d/utils/events/types.ts:86
Interface

FlamoClickEvent

独立页面 ↗#

Click, double-click, and context-menu activation payload.

类型
export interface FlamoClickEvent
返回 —来源 runtime/src/2d/utils/events/types.ts:97
Interface

FlamoKeyboardEvent

独立页面 ↗#

Keyboard payload routed to the focused Runtime entity.

类型
export interface FlamoKeyboardEvent
返回 —来源 runtime/src/2d/utils/events/types.ts:104
Interface

FlamoFocusEvent

独立页面 ↗#

Focus-transition payload for focus, blur, focusin, and focusout.

类型
export interface FlamoFocusEvent
返回 —来源 runtime/src/2d/utils/events/types.ts:113
Interface

FlamoDragEvent

独立页面 ↗#

Drag payload with the originating pointer and movement delta.

类型
export interface FlamoDragEvent
返回 —来源 runtime/src/2d/utils/events/types.ts:119
Interface

FlamoGestureEvent

独立页面 ↗#

Tap, long-press, pan, pinch, and rotate gesture payload.

类型
export interface FlamoGestureEvent
返回 —来源 runtime/src/2d/utils/events/types.ts:127
Interface

FlamoDomEvent

独立页面 ↗#

Input, composition, and clipboard payload bridged from an HTML Surface.

类型
export interface FlamoDomEvent
返回 —来源 runtime/src/2d/utils/events/types.ts:141