你好,我是 Kagol,个人公众号:前端开源星球

TinyVue 通过多层架构方法实现了精密的跨平台和跨框架兼容性,该方法将业务逻辑、平台展示和框架适配器分离。这种设计使单个代码库能够同时服务 Vue 2 和 Vue 3 应用程序,并同时支持 PC 和移动优先渲染模式。

架构概述

该架构采用无渲染组件模式,其中业务逻辑独立于渲染逻辑存在,并结合虚拟模块解析,通过统一的导入路径提供特定于框架的 API。

跨平台策略:PC 和移动优先

TinyVue 通过构建时配置而非运行时检测来实现平台差异化,确保每个目标平台获得最优的包大小和性能。

平台特定入口点

项目为不同平台提供专用入口点,包含精选的组件列表和模式配置:

PC 平台入口:

const appProperties = app.config?.globalProperties || app.prototype
appProperties.tiny_mode = { value: 'pc' }

移动优先平台入口:

const appProperties = app.config?.globalProperties || app.prototype
appProperties.tiny_mode = { value: 'mobile-first' }

平台特定入口点包含经过精心选择的组件集,针对各自的用例进行了优化。例如,PC 构建包含以桌面为中心的组件,如 GridDataTable 和复杂表单控件,而移动构建则优先考虑触控优化的组件,如 CascaderMobileSelectMobilePullRefresh 以及适合移动交互的导航模式。

模式配置在应用启动时通过 Vue 应用的全局属性注入全局,使其在整个组件树中可访问,无需 prop 传递。

组件架构差异

平台特定组件共享来自 @opentiny/vue-renderless 的相同无渲染逻辑,但实现了适合平台的模板:

方面 PC 组件 移动组件
触摸交互 以鼠标为中心,带悬停状态 触控优先,带滑动手势
布局模式 多列、密集布局 单列、可堆叠布局
输入方法 强调键盘快捷键 屏幕键盘优化
动画 微妙过渡 手势驱动动画
视口 桌面断点 移动断点

这种分离使开发者能够导入平台优化的包,而无需携带不必要的代码:

// 用于 PC 应用程序
import { TinyButton, TinyGrid } from '@opentiny/vue/pc'
 
// 用于移动优先应用程序  
import { TinyButton, TinyPullRefresh } from '@opentiny/vue/mobile-first'

跨框架策略:Vue 2 和 Vue 3 兼容性

TinyVue 设计中最精密的方面是通过精心设计的适配器层实现统一的 Vue 2 和 Vue 3 支持,该层抽象了框架差异,同时保持了 Vue 2 的 Composition API 兼容性。

虚拟模块解析架构

TinyVue 利用 TypeScript 的路径映射创建虚拟导入路径,根据构建配置解析为不同的实现,允许组件在框架版本间使用统一的 API 表面。

Vue 2 配置:

"paths": {
  "virtual:common/adapter/vue": ["packages/vue-common/src/adapter/vue2/index.ts"]
}

Vue 3 配置:

"paths": {
  "virtual:common/adapter/vue": ["packages/vue-common/src/adapter/vue3/index.ts"]
}

这种架构使所有组件导入都能引用相同的虚拟路径,而 TypeScript 和构建系统会解析为适当的实现:

// 在 Vue 2 和 Vue 3 中工作方式相同
import { defineComponent, ref, computed } from 'virtual:common/adapter/vue'

适配器层实现

适配器层为特定于框架的 API 提供统一抽象,处理组件 API、生命周期钩子、事件系统和组件树遍历的差异。

Vue 2 适配器:
Vue 2 适配器为 Vue 2.6 集成 @vue/composition-api,识别 Vue 2.7 内置的 Composition API 支持,并为组件渲染、父子遍历和事件分发模式提供 Vue 2 特定实现。

Vue 3 适配器:
Vue 3 适配器提供原生 Vue 3 实现,同时保持与 Vue 2 适配器相同的导出表面,直接使用 Vue 3 的 Composition API,并实现与 Vue 3 虚拟 DOM 结构兼容的组件树遍历。

无渲染组件模式

无渲染架构构成了跨平台和跨框架策略的基础。业务逻辑存在于 @opentiny/vue-renderless 包中,作为纯 TypeScript 函数,无框架依赖:

无渲染按钮逻辑

export const handleClick =
  ({ emit, props, state, designConfig }: Pick<IButtonRenderlessParams, 'emit' | 'props' | 'state' | 'designConfig'>) =>
  (event: MouseEvent): void => {
    const urlHref = xss.filterUrl(props.href)
    const DEFAULT_RESETTIME = 1000
    
    let resetTime = DEFAULT_RESETTIME
    
    if (props.resetTime !== DEFAULT_RESETTIME) {
      resetTime = props.resetTime
    }
    // ... 其余实现
  }

这个无渲染函数是框架无关的——它通过参数接收依赖并返回事件处理器。Vue 组件层导入此逻辑并将其适配到适当 Vue 版本的组件模型。

统一组件 API 表面

尽管内部框架存在差异,TinyVue 在 Vue 2 和 Vue 3 上提供了一致的组件 API。组件导出 PascalCase 和 kebab-case 名称以匹配生态系统约定:

组件导出:

export {
  ActionMenu,
  ActionMenu as TinyActionMenu,
  ActionSheet,
  ActionSheet as TinyActionSheet,
  Alert,
  Alert as TinyAlert,
  // ... 一致的命名模式
}

安装模式在框架间保持相同:

// 在 Vue 2 和 Vue 3 中均可工作
import { createApp } from 'vue'  // 或 Vue 2 的 'vue'
import TinyVue from '@opentiny/vue'
 
const app = createApp(App)
app.use(TinyVue)

构建系统集成

跨平台和跨框架能力通过精密的构建配置实现,该配置协调多个具有不同路径映射的 TypeScript 项目。

多目标构建过程

构建系统为每个目标组合生成单独的包:

构建目标 TypeScript 配置 适配器 模式 入口点
Vue 2 PC tsconfig.vue2.json vue2 pc packages/vue/pc.ts
Vue 3 PC tsconfig.vue3.json vue3 pc packages/vue/pc.ts
Vue 2 Mobile tsconfig.vue2.json vue2 mobile-first packages/vue/mobile-first.ts
Vue 3 Mobile tsconfig.vue3.json vue3 mobile-first packages/vue/mobile-first.ts

每个目标从相同的组件源代码构建,但使用不同的 TypeScript 编译器选项,将虚拟导入重定向到适当的适配器实现。

开发工作流示例

Vue 2 PC 开发设置

{
  "extends": "./tsconfig.vue2.json",
  "include": ["packages/**/*"],
  "paths": {
    "virtual:common/adapter/vue": ["packages/vue-common/src/adapter/vue2/index.ts"]
  }
}

Vue 3 移动优先开发设置

{
  "extends": "./tsconfig.vue3.json",
  "include": ["packages/**/*"],
  "paths": {
    "virtual:common/adapter/vue": ["packages/vue-common/src/adapter/vue3/index.ts"]
  }
}

这使开发者能够维护单一代码库,同时针对多个平台和框架,为每种场景提供最优的包组合。

优势和权衡

优点

跨平台和跨框架设计带来了显著的架构优势:

优势 影响
单一事实来源 业务逻辑在无渲染包中只存在一次
框架迁移路径 无需重写组件即可无缝从 Vue 2 升级到 Vue 3
平台优化 平台特定包避免携带未使用代码
统一 API 表面 跨目标提供一致的开发者体验
TypeScript 安全性 所有框架和平台组合的完整类型安全

架构考虑

该设计引入了需要仔细管理的特定复杂性:

  • 虚拟导入复杂性:开发者必须理解路径映射和虚拟模块
  • 适配器维护:框架适配器必须跟踪 Vue 版本变更
  • 包大小优化:需要仔细的排除策略以防止重复代码
  • 调试复杂性:堆栈跟踪可能引用磁盘上不存在的虚拟模块

无渲染模式结合虚拟模块解析创建了一个强大的抽象,能够在保持类型安全和开发者人体工程学的同时实现跨平台和跨框架兼容性。

这个架构基础使 TinyVue 能够服务于多样化的应用程序需求——从桌面企业应用程序到移动优先的消费者体验——同时在 Vue 框架版本间保持统一、可维护的代码库。

联系我们

GitHub:https://github.com/opentiny/tiny-vue(欢迎 Star ⭐)

官网:https://opentiny.design/tiny-vue

个人博客:kagol.com.cn

小助手微信:opentiny-official

公众号:OpenTiny

Logo

OpenTiny 是企业智能前端开发解决方案,以生成式 UI 和 WebMCP 两大自主核心技术为基础,加速企业应用的智能化改造。我们会在社区定期为大家分享一些前后端的技术文章。

更多推荐