Skip to content

0009. React 适配器直接挂载 Core

This page is only available in Chinese. It is shown in its original language.

  • Status: Proposed
  • Date: 2026-10-09
  • Deciders: 363045841(owner), tseka
  • Source: v1.1 ADR-006

Context

@363045841yyt/klinechart-react 目前只导出 KLineChartWC,它渲染由 Vue 打包的 <kline-chart> 自定义元素。v0.10.4 曾主动移除直连 Core 的工厂、hooks 和 KLineChart 组件,理由是 SSR 安全(docs/release/v0.10.4.md)。因此 v1.1 ADR-006 是对既有决定的反转,需要回答两点:

  1. SSR:Core 模块在加载期会访问浏览器全局(实测在 Node 中加载 config 时模块求值期即访问 localStorage;在 jsdom 等有 DOM 的环境中还会创建 canvas 并调用 getContext),静态导入会进入服务端求值路径。
  2. 功能对等:Web Component 带完整产品 UI(工具栏、指标、画线、设置、Agent 面板),直连适配器只有图表本身。

同时,docs/architecture/adapter-architecture.md §5.2 仍描述着已不存在的 useChart / KLineChart,文档与代码不一致。packages/angular 已经直接调用 createChartController,React 是三个适配器中唯一绕道 Vue 的。

Decision

React 包同时提供两个层级,KLineChartWC 保持不变:

导出用途Vue 运行时
KLineChartWC需要完整 KCQ 产品 UI 的 React 宿主需要
KLineChart、useKLineChart、useCoreSignal自建外围 UI 的宿主、Expo DOM component(ADR 0010)、未来的 React 产品 UI不需要

实现约束:

  • Core 只在客户端 effect 中通过动态 import() 加载,SSR 只输出容器节点。服务端渲染有专门测试(@vitest-environment node)。
  • 控制器创建是异步的:卸载或 StrictMode 双挂载时,迟到的控制器在 resolve 后立即 dispose()。
  • 挂载参数只在首次挂载时读取;之后 data、theme、settings 通过控制器方法增量同步,主题优先级与 Angular 适配器一致(显式 theme > settings.theme,auto 只注入系统主题)。
  • useCoreSignal 基于 useSyncExternalStore,与 Core signal 的引用相等语义一致,不做额外拷贝。
  • 控制器创建失败时抛给最近的 Error Boundary。

Consequences

  • v1.1 验收标准「React 直接使用 Core,无 Vue 运行时依赖」:做 tree-shaking 的打包器(Vite、webpack、Next)只用 KLineChart 时不会打入 Vue。Metro 不做 tree-shaking,会顺着 KLineChartWC 的动态导入把整套 Vue UI 和字体打进产物(P3 实测 14.5 MB),因此另设 @363045841yyt/klinechart-react/direct 入口,只含直连挂载。安装层面仍会装上 Vue 包,因为它是 dependencies;改为可选 peer 属于破坏性变更,留到下一个 minor。
  • 直连挂载依赖 Core 自建的 DOM 骨架(buildDom)。P3 发现该路径此前从未在真实浏览器中渲染验证:缺少 Vue 组件 CSS 对应的布局、WebKit 首帧不布局 pane、恢复的布局会清空挂载数据。三处已修复,并由 createChartController.directMount.test.ts 覆盖;packages/react/preview/direct.html 用于人工核对。宿主需提供有确定尺寸的容器。
  • 输入接线由 ADR 0008 P1b 的 bindChartInput 提供,与 Vue 组件共用;宿主可通过 input 选项注入拦截钩子,或传 false 自行转发事件。
  • adapter-architecture.md §5.2 更新为实际 API。
  • 如果 owner 仍倾向 v0.10.4 的单一 WC 路线,可以只合入 ADR、不合入代码;代码是纯增量,回滚即删除新文件和导出。

On this page