FlexUI ASCF 详细设计方案
1. 概述
@flexui/ascf 是 FlexUI 的 ASCF (Atomic Service Cross Framework) 接口适配器,为 @flexui/core 提供与小程序 HXML/CSS/JS 组件开发方式兼容的接口层。
1.1 设计目标
- 接口兼容:提供与 MiniProgram 自定义组件接口一致的 API 风格
- HXML/CSS 支持:结合 webpack 插件,支持
.hxml模板和.css样式文件 - ASCF 组件库:内置 ASCF 生态的预定义组件 (button, view, text, scroll-view 等)
- 渐进迁移:允许开发者从 MiniProgram 生态平滑迁移到 FlexUI
1.2 包信息
| 字段 | 值 |
|---|---|
| 包名 | @flexui/ascf |
| 版本 | 0.1.0 |
| 语言 | TypeScript |
| 构建 | Rollup |
| 入口 | dist/flexui_ascf.js / dist/flexui_ascf.es.js |
| 组件入口 | dist/flexui_ascf_components.js |
2. 架构设计
┌──────────────────────────────────────────────────────┐
│ 应用代码 (HXML/CSS/JS) │
├──────────────────────────────────────────────────────┤
│ @flexui/ascf (接口适配层) │
│ ├── Component() → 组件定义 (类 MiniProgram API) │
│ ├── Behavior() → 行为复用 │
│ ├── Backend → ASCF 运行时后端 │
│ ├── Space → 组件空间管理 │
│ ├── Builder → 构建器链式 API │
│ └── components/ → 内置 ASCF 组件 │
├──────────────────────────────────────────────────────┤
│ @flexui/core (核心引擎) │
└──────────────────────────────────────────────────────┘
3. 核心模块
3.1 Component API
提供与 MiniProgram Component() 构造函数兼容的接口:
// ASCF 风格的组件定义
Component({
data: { count: 0 },
properties: { title: String },
methods: {
increment() { this.setData({ count: this.data.count + 1 }) }
},
lifetimes: {
attached() { /* ... */ },
detached() { /* ... */ },
},
})
与 @flexui/core 的映射关系:
Component(options)→ComponentSpace.defineComponent(params)Behavior(options)→ComponentSpace.defineBehavior(params)this.setData()→GeneralComponent.setData()this.triggerEvent()→GeneralComponent.triggerEvent()
3.2 Backend(ASCF 运行时后端)
backend.ts 提供 ASCF 运行环境的 Backend 实现:
ASCF Backend
├── 元素创建与销毁
├── 属性设置与样式应用
├── 事件绑定与分发
└── 与 ASCF 原生层的通信
3.3 ComponentSpace(组件空间)
space.ts 封装了 ASCF 的组件注册和全局配置:
ASCF ComponentSpace
├── 全局组件注册: usingComponents
├── 全局样式: app.css
├── 环境变量: env.ts (设备信息、系统信息)
└── 组件隔离策略: styleIsolation
3.4 Builder(构建器)
builder/ 目录提供与核心框架行为定义相关的构建器辅助功能。
3.5 内置组件
components/ 目录包含 ASCF 生态的预定义组件:
| 组件 | 说明 |
|---|---|
| view | 基础容器,对应 <div> |
| text | 文本节点,支持 selectable |
| image | 图片显示 |
| button | 按钮,支持多种样式 |
| scroll-view | 可滚动容器 |
| input | 输入框 |
| textarea | 多行输入 |
| swiper | 轮播组件 |
| icon | 图标组件 |
3.6 选择器查询 (SelectorQuery)
selector_query.ts 提供类 MiniProgram 的节点查询 API:
const query = this.createSelectorQuery()
query.select('.my-class').boundingClientRect()
query.selectAll('.item').fields({ rect: true, size: true })
query.exec((results) => { /* ... */ })
3.7 IntersectionObserver
intersection.ts 提供节点相交状态观测:
const observer = this.createIntersectionObserver()
observer.relativeTo('.container').observe('.target', (res) => {
console.log(res.intersectionRatio)
})
3.8 MediaQuery
media_query.ts 提供媒体查询观测:
const observer = this.createMediaQueryObserver()
observer.observe({ minWidth: 375 }, (matches) => { /* ... */ })
3.9 ResizeObserver
resize.ts 提供节点尺寸变化观测。
3.10 屏幕事件(窗口尺寸变化)
screen_events.ts 提供「页面显示区域尺寸变化」事件,对齐小程序语义(基础库 ≥ 2.4.0)。
完整设计(链路/分层/边界/多 scope 隔离/验证)见
docs/design/screen-events.md。
示例:
// 页面(根组件)自身回调
Page({
onResize(res) {
res.size.windowWidth // 新的显示区域宽度
res.size.windowHeight // 新的显示区域高度
},
})
// 自定义组件:页面尺寸变化时整棵组件树收到 resize
Component({
pageLifetimes: {
resize(res) { /* res.size.windowWidth / windowHeight */ },
},
})
事件来源:
- 引擎卡片链路(OHOS/Android FlexView):原生容器尺寸变化 →
updateDimension→Dimensions.set(携带__rootId__)→NativeBackendContext.setWindowSize(按 rootId 路由 + 真实宽高变化检测)→ 变化时经__GLOBAL__.__flexuiScreenResizeListeners广播(白名单通道,同 Dimensions/colorMode 监听器模式); - 其它宿主(浏览器预览/测试):直接调用
notifyScreenResize(rootId, width, height)。
分发:页面根组件(Root)构造时注册(registerRootForScreenResize,按 backend
duck-typing 的 rootViewId 精确路由,卡片 A 的容器变化不会误触发卡片 B):
- 页面根组件顶层
onResize(Page 定义顶层函数字段注册为组件方法,未声明则 no-op); - 整棵页面树的
pageLifetimes.resize(triggerPageLifetime('resize', [res])递归 含根组件自身与全部自定义组件)。
回调异常遵循框架规则:onResize 调用捕获后 dispatchError 上报(不 rethrow),
pageLifetimes.resize 由 FuncArr safeCallback 兜底。事件载荷与 selectViewport()
同源(均取 backend 的权威窗口尺寸)。
3.10 Harmony 适配
harmony/ 目录提供 HarmonyOS 平台的特化适配。
4. 与 @flexui/core 的关系
@flexui/ascf 作为 @flexui/core 的 peerDependency 存在,它不重复实现核心功能,而是:
- 接口翻译:将 MiniProgram 风格的 API 映射到 FlexUI Core API
- 约定增强:提供 ASCF 生态特有的组件、约定和开发模式
- 构建集成:与 webpack 插件配合,实现 HXML/CSS 的编译
5. 构建集成
5.1 配合 webpack 插件
// webpack.config.js
const { FlexUIAscfWebpackPlugin } = require('flexui-webpack-plugin')
module.exports = {
plugins: [
new FlexUIAscfWebpackPlugin({ path: './src' })
],
module: {
rules: [
{ test: /\.hxml$/, use: 'flexui-webpack-plugin/hxml_loader' },
{ test: /\.css$/, use: 'flexui-webpack-plugin/css_loader' },
]
}
}
5.2 包的分离导出
@flexui/ascf → 核心适配器 API
@flexui/ascf/components → 内置组件导出
6. 类型定义
types.ts 定义了 ASCF 适配层使用的关键类型,包括组件选项、HXML 相关类型、运行时环境类型等。
7. 设计决策
7.1 为什么不直接在 @flexui/core 中实现 ASCF 兼容?
- 关注点分离:核心框架保持纯净,不依赖任何特定生态
- 可替换性:其他适配器 (如 React/Vue 适配) 可以独立开发
- 体积控制:不需要 ASCF 兼容的应用不必加载这层
7.2 为什么使用 peerDependency?
@flexui/ascf 声明 @flexui/core 为 peerDependency,确保:
- 应用可以控制核心框架的版本
- 避免多个 core 实例共存导致的状态不一致
7.3 组件导出策略
内置组件通过 @flexui/ascf/components 子路径独立导出:
- 需要内置组件时显式导入,不增加基础包体积
- Tree-shaking 友好,未使用的组件不会被打包