DirectSurface UIDirectSurface UI
开始使用
文档/API 参考

Core API 参考

本文示例使用以下公共入口:

import {  DisposableBag,  RenderPage,  createAppContext,  createAppContextKey,} from 'ds-ui'

Core API 是框架最底层的能力集合,包括 render tree、布局约束、焦点、输入、剪贴板、Popup、上下文、命令、状态绑定和资源释放。业务开发通常优先使用 Widgets APILayout API;只有开发可复用组件、诊断工具或框架扩展时,才需要直接接触 Core API。

导出清单

状态和生命周期:

  • Disposable
  • DisposeFn
  • DisposableBag
  • BindingBag
  • bindSelector
  • ScheduleFn
  • ScheduleMode
  • createStore
  • Store

Render tree 和布局协议:

  • RenderObject
  • PipelineOwner
  • BoxConstraints
  • LayoutContext
  • LayoutPassKind
  • RenderLifecycleAware
  • RenderLoadedContext
  • Offset
  • Rect
  • Size
  • constrainSize
  • tightConstraints
  • looseConstraints

焦点和输入:

  • FocusManager
  • FocusScope
  • FocusScopeType
  • Focusable
  • InputComposer
  • InputSession
  • InputSessionToken

剪贴板:

  • ClipboardController
  • ClipboardTextWriter
  • CopyableSelection
  • isCopyShortcut
  • isCopyableSelection

App Context 和命令:

  • APP_CONTEXT_PROVIDER
  • AppContextKey
  • AppContextRegistry
  • AppContextInitialValues
  • AppContextLookupKey
  • AppContextProvider
  • AppContextSetOptions
  • createAppContext
  • createAppContextKey
  • isAppContextProvider
  • COMMAND_SCOPE_PROVIDER
  • CommandManager
  • CommandScope
  • CommandShortcutController
  • allowAllPermissionService
  • commandManagerContextKey
  • isCommandScopeProvider

Popup、锚点和滚动视口:

  • PopupManager
  • Popup
  • PopupAnchorMode
  • PopupContext
  • PopupContextProvider
  • PopupOpenOptions
  • PopupPaintInvalidator
  • PopupViewport
  • OverlayInvalidator
  • OverlayPaintInvalidator
  • GET_POPUP_ANCHOR_RECT
  • PopupAnchor
  • PopupAnchorPlacement
  • PopupAnchorTarget
  • resolvePopupAnchorRect
  • resolvePopupAnchorTarget
  • ScrollViewport
  • ScrollViewportClient
  • isScrollViewportClient

事件和命中测试:

  • HitTestResult
  • DispatchPhase
  • DispatchEvent
  • HitTestEntry
  • HitTestTarget
  • PointerEvent
  • WheelPointerEvent
  • EventDispatcher
  • InteractiveRenderObject
  • PointerDispatchDebugSnapshot
  • isPrimaryPointerButton

绘制:

  • PaintContext

RenderObject

RenderObject 是所有可布局、可绘制、可命中的对象基类。业务组件通常继承 RenderBox 或已有 widget;只有实现底层渲染协议时才直接继承 RenderObject

常用职责:

  • 持有 parentowneroffsetsize
  • 参与 attach / detach / dispose 生命周期。
  • 通过 markNeedsLayout()markNeedsPaint()markNeedsTransientPaint() 请求管线刷新。
  • 通过 paintBounds 声明包含阴影等视觉溢出的绘制区域;仅移动节点时用 markNeedsPaintForGeometryChange() 累计旧、新损伤区域。
  • 通过 visible 控制折叠隐藏;不可见时尺寸为 0,不参与 layout、paint、hit test 和焦点。
  • 通过 hitTest()hitTestPath() 参与事件命中。
  • 通过 debugInfo() 暴露布局检查信息。
  • 通过 getAppContext() / requireAppContext() 读取当前 render tree 的上下文。

自定义组件原则:

  • 在属性 setter 中判断值是否变化,再标记 layout 或 paint。
  • layout 外修改 offset 时先保存旧 paintBounds,再调用 markNeedsPaintForGeometryChange()
  • 不要在 performPaint() 中修改布局相关状态。
  • 维护好子节点的 parent,替换子节点时处理 detach。
  • dispose() 中释放订阅、定时器、popup、输入会话和外部资源。

PipelineOwner

PipelineOwner 管理 layout、paint、transient paint 和 app context。

常见调用方是 runtime,不是业务页面。组件应通过自身的 markNeedsLayout() / markNeedsPaint() 进入管线,不要直接操作 pipeline 内部队列。

相关概念:

概念 说明
layout 重新计算尺寸和 offset。
paint 重新绘制稳定图层内容。
transient paint 光标闪烁、临时 overlay 等不应触发完整 layout 的轻量绘制。
app context 当前 runtime 根上下文。

约束和几何类型

BoxConstraints

字段 类型 说明
minWidth number 最小宽度。
maxWidth number 最大宽度。
minHeight number 最小高度。
maxHeight number 最大高度。

几何类型:

类型 字段
Offset { x: number; y: number }
Size { width: number; height: number }
Rect { x: number; y: number; width: number; height: number }

工具函数:

函数 说明
constrainSize(constraints, size) 把自然尺寸限制到约束范围内。
tightConstraints(width, height) 生成固定尺寸约束。
looseConstraints(width, height) 生成最小为 0、最大为指定宽高的约束。

FocusManager

焦点系统负责当前键盘和输入目标。

核心导出:

  • FocusManager
  • FocusScope
  • FocusScopeType
  • Focusable

Focusable 对象通常实现:

  • focusIn()
  • focusOut()
  • onKeyDown(event)

焦点规则:

  • Popup 打开时会建立 popup focus scope。
  • 最后一个交互 popup 关闭时恢复之前焦点。
  • 组件 dispose 时应从焦点系统注销,避免旧对象继续接收键盘事件。

业务页面通常不直接操作 FocusManager;输入控件、窗口、popup 和 runtime 会处理大部分焦点流转。

InputComposer

InputComposer 是隐藏输入承接器,负责键盘输入、中文 composition、粘贴和文本输入会话。

核心导出:

  • InputComposer
  • InputSession
  • InputSessionToken

使用边界:

  • 隐藏输入控件只承接当前输入,不应保存整份大文档。
  • 大文本粘贴应从 paste event 读取文本后直接写入文档模型,并阻止默认落入 textarea。
  • composition update 可以更新预编辑文本;composition end 再提交最终文本。
  • 页面或组件销毁时要结束输入会话。

普通输入组件和文本编辑器已经封装输入会话,业务页面不应直接访问隐藏输入控件。

ClipboardController

剪贴板系统统一处理复制快捷键和可复制选区。

核心导出:

  • ClipboardController
  • ClipboardTextWriter
  • CopyableSelection
  • isCopyShortcut
  • isCopyableSelection

CopyableSelection 组件应提供 getCopyText(),返回当前选区对应文本。TreeView、GridView、ObjectInspector、MarkdownViewer、PlainTextEditor 都应复用这套语义。

使用边界:

  • 组件只负责提供文本,不直接调用浏览器剪贴板 API。
  • 剪贴板写入失败要允许业务或运行时降级处理。
  • 调试类组件复制对象时,应复制可读的 key path 和完整值摘要。

App Context

App Context 用于按范围传递依赖对象。它的详细 API 见 App Context API

最小示例:

const coreNameKey = createAppContextKey<string>('currentName')const coreContext = createAppContext()coreContext.set(coreNameKey, '示例')const coreName = coreContext.require(coreNameKey)coreName.length

关键边界:

  • key 定义在稳定模块,读取端和写入端复用同一个 key。
  • 页面级对象放页面 scope,不放应用根。
  • controller、订阅和定时器使用 setDisposable() 或自定义 disposer。

Commands

命令系统统一按钮、菜单、快捷键、权限和启用状态。详细 API 见 Commands API

核心对象:

  • CommandManager
  • CommandScope
  • CommandShortcutController
  • RenderCommandScope
  • RenderCommandButton
  • RenderCommandToolbar

关键边界:

  • 命令是业务动作,不是按钮。
  • 页面命令注册在页面 scope,随页面释放。
  • canExecute 是轻量同步求值,不做网络请求和重计算。
  • 状态变化后调用 commandManager.invalidate()

Popup 底层能力包括:

  • PopupManager
  • Popup
  • PopupAnchorMode
  • PopupContext
  • PopupContextProvider
  • PopupOpenOptions
  • OverlayInvalidator
  • GET_POPUP_ANCHOR_RECT
  • resolvePopupAnchorRect
  • resolvePopupAnchorTarget

详细说明见 Popup 弹出层

关键边界:

  • 普通业务优先使用 Dropdown、DatePicker、Popover、Modal、Drawer 等上层组件。
  • 自定义 popup 要处理 hit test、外部点击、Escape、滚轮、focus 和 close 释放。
  • 锚点位置应动态读取,不能只在打开时缓存一次。
  • 页面销毁时关闭 owner 关联 popup。

ScrollViewportClient

ScrollViewportClient 用于让外部滚动容器把可视区域同步给子组件。Masonry、虚拟列表、文档查看器等可以据此减少不可见区域计算。

导出:

  • ScrollViewport
  • ScrollViewportClient
  • isScrollViewportClient

如果组件实现了 setScrollViewport(viewport)RenderScrollViewer 会在 layout 和滚动时同步可视信息。

EventDispatcher 和命中测试

事件系统负责从 canvas 事件到 render tree 的路由。

核心导出:

  • EventDispatcher
  • HitTestResult
  • DispatchPhase
  • PointerEvent
  • WheelPointerEvent
  • InteractiveRenderObject
  • isPrimaryPointerButton

业务组件实现复杂交互时应通过 hitTestPath()onPointerDown()onPointerMove()onWheel() 等协议接入,不要直接监听全局 DOM 事件。

DisposableBag

DisposableBag 用于集中释放资源。

适合注册:

  • 事件监听。
  • store 订阅。
  • popup / overlay close 句柄。
  • 定时器释放函数。
  • 业务 controller。

页面、弹窗、控制器和复杂组件都应在 dispose() 中释放自己的 DisposableBag

class AutoRefreshPage extends RenderPage {  private readonly disposables = new DisposableBag()   constructor() {    super()     this.disposables.setInterval(() => {      reload()    }, 30000)  }   override dispose(): void {    this.disposables.dispose()    super.dispose()  }}

如果资源生命周期跟页面上下文一致,也可以把 DisposableBag 通过 AppContextRegistry.setDisposable() 托管给页面 context。

BindingBag 和 Store

createStore() / Store 提供轻量状态容器,BindingBag / bindSelector() 提供把状态投影绑定到组件属性的能力。

适合场景:

  • demo 和轻量页面状态。
  • UI 局部状态同步。
  • 将 store selector 的变化调度到组件更新。

复杂业务系统可以接入自己的状态管理方案。框架不会强制业务状态必须放入 Store

PaintContext

PaintContext 是绘制上下文封装,组件 paint 阶段通过它访问 canvas 2D context、主题和绘制辅助能力。

业务页面通常不直接使用 PaintContext。只有开发自绘组件、图表、条码、编辑器或文档渲染器时才需要关注。

使用边界

  • 业务页面优先使用 widgets 和 layout API。
  • 自定义通用组件时再深入 core API。
  • 不要依赖未从包入口导出的内部 helper。
  • 不要在业务层直接操作 render tree 私有字段。
  • 不要在 paint 中触发 layout 或业务副作用。
  • 管线调度、频繁重绘、焦点异常优先用运行时诊断定位。

相关文档