Skip to content

在宿主框架中使用 ElfUI ​

ElfUI 组件是标准 Custom Element。原生 DOM、React、Vue、Svelte、Angular 或其他宿主应通过 property、attribute、CustomEvent、slot、CSS custom property、::part()、焦点方法与原生表单行为集成,不需要 ElfUI 专用 renderer adapter。

共享宿主契约 ​

关注点契约
基础类型 attribute字符串按已声明 prop options 转换。
object/array/function使用 property 赋值;ElfUI 保留宿主拥有的引用身份。
更新替换已声明 property 会触发响应式更新,不会替换 Custom Element 节点。
事件监听标准 CustomEvent;payload 位于 detail。
Shadow DOM 传播只有需要跨边界的事件才开启 bubbles / composed。
子内容通过默认 slot 或带 slot attribute 的 named slot 传入 Light DOM。
样式使用 CSS custom property 与组件公开的 ::part()。
焦点与方法在元素实例上调用 defineExpose() 暴露的方法。
表单form-associated 组件通过原生 Custom Element internals 参与表单。
卸载移除 host 会释放组件拥有的 effect 与外部资源。

已声明 props 的 property accessor 会在元素构造后、连接前就存在,使宿主能够选择 property 赋值并保留 object、array、function 的引用身份。通用做法是拿到 DOM 节点后直接赋值:

ts
const element = document.querySelector("elf-data-grid")!;
element.rows = rows;
element.formatter = formatter;
element.addEventListener("row-select", (event) => {
  const row = (event as CustomEvent<Row>).detail;
});

不同宿主的模板语法不同,但底层契约相同。如果宿主对未知自定义事件有额外规则,addEventListener() 始终是平台级兜底方式。

注册与多 App ​

即使 ElfUI App 的配置、插件、指令和依赖注入彼此隔离,Custom Element 注册仍是页面全局的。应用与组件库应使用稳定且唯一的 tag 前缀。相同构造器重复注册是幂等的;不同构造器占用同一 tag 会抛出 ELF_CUSTOM_ELEMENT_CONFLICT。

如果启动顺序由宿主控制,可用 register: false 定义组件,再在客户端入口调用 registerComponents()。不要让两份被打包的 ElfUI runtime 用同一个 tag 注册不同实现。

SSR 宿主 ​

ElfUI 包与编译后的组件模块可以在没有浏览器全局对象的环境中安全 import,服务端会得到只含元数据的占位构造器。DOM 创建、显式注册和 createApp().mount() 仍只能在客户端执行。

ElfUI 当前支持服务端输出 Custom Element host 外壳,不支持服务端渲染组件 Shadow DOM,也不 hydration 组件内部 DOM。SSR 框架应把 ElfUI 组件视为 client-only island,并确保组件模块在浏览器端重新求值。

已测试兼容基线 ​

发布门禁当前会在真实浏览器中,让 native DOM、React 19.2.7、Vue 3.5.40、Svelte 5.56.6、Angular 22.0.7 运行相同的 property/update/remount、attribute/event、slot/style/focus/form、keyed list/资源清理契约,并验证多个隔离 App 与多份 runtime。

这是已测试基线,不代表任意宿主版本或 wrapper 库都天然兼容。升级 ElfUI 或宿主框架时,应保留一组由应用自己维护的小型集成测试。