核心用法
fosmvvm-leaf-view-generator 是 FOSMVVM 架构中的视图层生成工具,用于创建 Swift Vapor 框架的 Leaf 模板。该技能基于 View-ViewModel 命名对齐原则:Leaf 文件名必须与对应的 ViewModel 名称匹配,确保代码可发现性和可维护性。
支持两种模板类型:
- 完整页面模板:继承基础布局,包含
<html>、<head>、<body>,用于初始页面加载 - 片段模板:无布局扩展,单一根元素,用于 HTML-over-the-wire 动态更新
HTML-over-the-Wire 模式
该模式是技能的核心亮点:JavaScript 事件 → WebApp 路由 → 服务器处理 → 返回 HTML → DOM 替换,无需客户端 JSON 解析和渲染。片段模板通过 data-* 属性嵌入状态(如 data-{entity}-id、data-status),供 JavaScript 读取以构建后续请求。
关键模式
1. 数据属性状态管理:片段必须嵌入 JavaScript 所需的原始状态值(枚举原始值),而非本地化显示名称
2. 自动本地化渲染:Localizable 类型通过 LeafDataRepresentable 自动本地化,模板中直接使用 #(property)
3. ViewModel 属性设计:区分原始值(用于 data-* 属性)和本地化显示值(用于渲染)
4. Codable 约束:只有存储属性会被编码到 Leaf,计算属性需在 init() 中预计算并存储
显著优点
- 架构一致性:强制 View-ViewModel 命名对齐,提升代码库可导航性
- 服务端渲染优势:HTML-over-the-wire 减少客户端复杂度,首屏加载更快,SEO 友好
- 类型安全:错误类型在编译期已知,无需运行时类型发现
- 国际化内置:
Localizable协议自动处理日期、数字、字符串的本地化 - 与 SwiftUI 共享 ViewModel:同一 ViewModel 同时服务 Web 和原生客户端
潜在缺点与局限性
- Leaf 语法局限:数组下标访问未文档化,需通过 ViewModel 预计算
- 模板拼接风险:直接拼接本地化值会破坏 RTL 语言支持,必须使用
@LocalizedSubs - 日期格式化约束:模板中硬编码日期格式违反本地化原则,应使用
LocalizableDate - SwiftUI 耦合:Leaf ViewModel 需正确初始化
vmId,否则影响 SwiftUI 客户端的视图更新 - 生态锁定:深度绑定 Vapor + Leaf 技术栈,迁移成本较高
适合人群
- 使用 Swift Vapor 构建 Web 应用的全栈开发者
- 需要为现有 SwiftUI 应用添加 Web 客户端的团队
- 偏好服务端渲染、追求简化前端架构的工程师
- 需要强类型安全、厌弃 JavaScript 运行时错误的开发者
常规风险
| 风险类别 | 描述 | 缓解措施 |
|---------|------|---------|
| 命名不一致 | 模板与 ViewModel 文件名不匹配导致渲染失败 | 严格遵守 `{Entity}CardView.leaf` ↔ `{Entity}CardViewModel.swift` 约定 || 状态数据错误 | 将本地化显示名存入 `data-*` 属性,导致 JS 请求 payload 无效 | 始终存储原始枚举值,单独提供 `xxxDisplay` 属性 |
| 视图不更新 | `vmId` 使用通用初始化导致 SwiftUI 身份判断失效 | 使用 `.init(id:)` 或至少 `.init(type: Self.self)` |
| RTL 布局破坏 | 模板级字符串拼接假设从左到右顺序 | 所有组合文本通过 `@LocalizedSubs` 在 ViewModel 层处理 |
| 计算属性丢失 | 依赖 Swift 计算属性在 Leaf 中显示数据 | 在 `init()` 中计算并存储为属性 |
版本与演进
最新 v2.4(2026-01-24)采用上下文感知设计:技能自动引用对话上下文中的 ViewModel 定义,无需文件路径或问答交互,实现更流畅的开发体验。