6.0 KiB
6.0 KiB
Context
当前前端项目使用 Vue 3 + Vant UI 构建,虽然已有封装的 PopupContainer.vue 组件,但项目中存在多种弹窗实现方式:
- PopupContainer.vue: 统一的底部弹出式弹窗,支持标题、副标题、固定头部/页脚、内容滚动
- AddClassifyDialog.vue: 基于
van-dialog的独立对话框组件,用于新增分类 - CategoryBillPopup.vue: 基于
van-popup的独立底部弹窗组件,用于展示分类账单列表 - 直接使用 van-dialog: 多个视图文件中直接使用(如 ClassificationEdit.vue、BillAnalysisView.vue)
- 直接使用 van-popup: 多个视图文件中用于选择器、表单等场景(如 PeriodicRecord.vue、statisticsV2/Index.vue)
这种分散的实现导致:
- 弹窗风格不统一(标题样式、圆角、间距、字体大小等)
- 代码重复度高,维护成本高
- 用户体验不一致
Goals / Non-Goals
Goals:
- 统一所有弹窗组件使用
PopupContainer或其扩展组件 - 确保弹窗的视觉风格和交互行为一致
- 减少代码重复,提高可维护性
- 扩展
PopupContainer功能以覆盖现有所有使用场景
Non-Goals:
- 不修改 Vant UI 组件库本身
- 不改变弹窗的业务逻辑(仅重构 UI 层)
- 不影响后端 API
Decisions
1. 扩展现有 PopupContainer 组件而非创建新组件
选择理由:
PopupContainer.vue已有成熟的底部弹窗布局和样式- 仅需扩展其功能即可覆盖大部分使用场景
- 避免引入新的组件,减少学习成本
扩展点:
- 添加
confirm和cancel事件,支持简单确认对话框场景 - 添加
showConfirmButton和showCancelButtonprops,控制按钮显示 - 添加
confirmText和cancelTextprops,自定义按钮文本 - 保留插槽机制,支持复杂表单场景
2. 保留 PopupContainer 的插槽设计
选择理由:
- 插槽提供最大的灵活性,支持任意复杂的内容
- 现有代码已使用插槽模式(header-actions、footer),保持向后兼容
- 避免 API 过度设计,保持组件简洁
3. 渐进式迁移策略
选择理由:
- 42+ 处弹窗修改,一次性重构风险高
- 分批迁移便于测试和回滚
- 降低对现有功能的影响
迁移顺序:
- 扩展
PopupContainer组件 - 迁移
AddClassifyDialog.vue和CategoryBillPopup.vue - 迁移
views/目录中的弹窗,按功能模块分批
4. 不删除 AddClassifyDialog 和 CategoryBillPopup 组件文件
选择理由:
- 这两个组件封装了特定的业务逻辑(如表单验证、数据加载)
- 可以将它们改造为使用
PopupContainer的组合组件,保留业务逻辑 - 避免破坏其他引用这些组件的地方
改造方式:
- 将
AddClassifyDialog.vue改造为使用PopupContainer的组合组件 - 将
CategoryBillPopup.vue改造为使用PopupContainer的组合组件 - 组件 API 保持不变,仅内部实现变更
5. 使用 Vant UI 的 CSS 变量
选择理由:
- 项目已使用 Vant UI,保持视觉一致性
- 支持深色/浅色主题切换
- 减少自定义 CSS 代码量
Risks / Trade-offs
1. 扩展 PopupContainer 可能导致 API 膨胀
风险: 扩展功能过多后,组件变得复杂,难以维护
缓解措施:
- 保持核心 API 简洁,使用插槽处理复杂场景
- 添加清晰的文档和示例
- 考虑拆分为多个专用组件(如 ConfirmDialog、FormDialog)如果过于复杂
2. 迁移过程中可能引入 Bug
风险: 重构可能破坏现有功能
缓解措施:
- 渐进式迁移,每批迁移后进行完整测试
- 保留旧代码作为参考,直到新代码稳定
- 重点测试弹窗的打开/关闭、表单验证、数据加载等交互
3. 某些场景可能不适用 PopupContainer
风险: 一些特殊的弹窗场景(如全屏弹窗、居中弹窗)无法用底部弹窗实现
缓解措施:
- 识别这些特殊场景,评估是否需要保留
van-dialog或创建新的专用组件 - 优先统一常见场景,特殊场景可以例外
4. 性能影响
风险: 组件封装层可能增加轻微的性能开销
缓解措施:
- 保持组件轻量化,避免不必要的响应式依赖
- 使用 Vue 3 的
<script setup>语法,减少运行时开销 - 进行性能测试,确保没有明显退化
Migration Plan
阶段 1: 扩展 PopupContainer 组件
- 添加确认对话框相关 props(
showConfirmButton、showCancelButton、confirmText、cancelText) - 添加
confirm和cancel事件 - 更新样式,确保与现有设计一致
- 编写组件文档和示例
阶段 2: 改造现有封装组件
- 改造
AddClassifyDialog.vue,使用PopupContainer实现 - 改造
CategoryBillPopup.vue,使用PopupContainer实现 - 测试改造后的组件功能
阶段 3: 迁移 views/ 目录中的弹窗
按功能模块分批迁移:
- 分类相关视图(ClassificationEdit.vue、ClassificationBatch.vue 等)
- 账单相关视图(PeriodicRecord.vue、TransactionsRecord.vue 等)
- 统计相关视图(statisticsV2/Index.vue 等)
- 预算相关视图(budgetV2/*.vue)
- 其他视图(BillAnalysisView.vue、calendarV2/Index.vue 等)
阶段 4: 验证和优化
- 全量测试所有弹窗功能
- 性能测试和优化
- 代码审查和清理
- 更新文档
回滚策略
- 使用 Git 分支进行开发,主分支保持稳定
- 每个阶段完成后打 Tag,便于快速回滚
- 保留旧的实现代码,直到新代码完全稳定
Open Questions
-
是否需要创建专门的
ConfirmDialog组件?- 当前考虑扩展
PopupContainer以支持确认对话框场景 - 如果确认对话框的使用场景较多且简单,可以考虑独立组件
- 当前考虑扩展
-
如何处理全屏弹窗场景?
- 识别项目中是否存在全屏弹窗需求
- 如有,评估是否需要扩展
PopupContainer或创建新组件
-
弹窗动画是否需要统一?
- 当前依赖 Vant UI 的默认动画
- 如有特殊需求,可能需要自定义动画