背景
某天,闲着没事干,打算对之前写过的一个C端优惠弹窗的代码进行重构,之前写的时候思考不成熟,虽然能用,但从代码角度和前期设计角度来说是有很大缺陷,也不方便维护,具体UI如下

核心交互流程:点击底部优惠设置按钮 -> 唤起优惠设置弹窗 -> 设置优惠信息
弹窗交互流程:
- 点击优惠信息 -> 唤起弹窗 -> 变更优惠数据 -> 点击优惠弹窗里的确认选择(必填校验) -> 设置优惠信息 -> 下次进来继续保留优惠信息
- 点击优惠信息 -> 唤起弹窗 -> 重置优惠信息 -> 下次进来就是空的
- 点击优惠信息 -> 唤起弹窗 -> 变更里面的优惠数据 -> 不点击确认选择 -> 关闭弹窗 -> 下次进来还是原来的数据
- 点击优惠信息 -> 唤起弹窗 -> 变更里面的优惠数据 -> 点击确认选择 -> 关闭弹窗 -> 下次进来数据已经是最新的了
需求核心目的:设置商品的优惠
重构实施过程
- 需求与交互分析
- 根据需求与业务建立行为模型
- 根据行为模型建立代码结构
- 代码细节优化
tip: 写代码要有抽象思维
根据需求与业务建立行为模型
在对需求和交互经过了分析之后,大部分前端开发者都能知道的交互流程是啥样了,哪里放按钮,哪里放弹窗,弹窗里布局是啥,什么时候唤起弹窗等
此时这里就有1个点可以注意下:
UI 差异 ≠ 交互逻辑差异
,底层行为模型可以复用
简单来说就是:你有没有做过相关功能,可以用来类比;有没有不同的UI,但实际背后是同样逻辑的情况
为什么会有这里要这么说呢,因为这个C端的弹窗功能,有个很好的类比对象------------B端的表格筛选和唤起表单弹窗更新数据,以FastAdmin举例,如下


这两者UI完全不一样,但行为模型是一样,我们来拆解下
- C端优惠弹窗:点击优惠设置按钮 -> 唤起弹窗 -> 可以对优惠信息进行编辑 -> 确认时保存数据/取消时不保存数据
- B端附件管理:在表格里点击编辑按钮 -> 唤起弹窗 -> 可以对附件信息进行编辑 -> 确认时保存数据/取消时不保存数据
此时你就会发现,问题简单化了
因为B端的这套流程,对于大部分前端开发人员来说是开发过很多遍的,所以是非常熟练的,而C端弹窗的基本交互流程也是和B端弹窗交互流程是一致的,所以行为模型是可以复用的,进而代码设计来说是可以复用的
这里我们联系背景里说的交互流程,进行对比下
- C端的优惠信息那一栏,也就是展示底部展示优惠信息那一栏 可以看成 B端我们点击编辑按钮的那一行,他们具备共同点,都有数据展示,都有按钮唤起弹窗


那这样其实C端的优惠弹窗从代码设计来说,就有2个核心变量了,data
和form
- data:优惠的真实数据,用来展示外部的优惠金额数据(根据优惠信息进行计算)
- form:优惠弹窗里的数据,因为优惠弹窗涉及到数据变更,只有点击确认选择才会更新数据,不点击确认选择,下次进来还是原来的数据
- 这一点和B端的表单弹窗行为逻辑很像,B端的弹窗打开依赖于我们点击的这一行的数据,比如id,通过Id调用他的最新数据,你在里面进行随便编辑,只要不点击保存,下次进来就还是原来的数据;你点击关闭就是关闭弹窗,重置表单
那我们B端的变量设计其实也是一样的,会有tableData进行列表渲染,然后会维护一个form表单数据用来展示弹窗里的信息
然后还有交互逻辑,我们先讲讲B端的弹窗基本交互
- 打开弹窗:获取点击到的表格项里的数据 -> 唤起弹窗 -> 然后将里面数据覆盖到form表单里
- 关闭弹窗:关闭弹窗 -> 重置表单
- 确认:校验数据有效性 -> 更新数据 -> 关闭弹窗
- 弹窗编辑:编辑弹窗里的信息,只要不点击确认,下次进来还是原来的
那么C端的优惠弹窗交互来说也是类似的逻辑
- 打开弹窗:唤起弹窗 -> 将data,也就是优惠真实数据覆盖到form表单数据里
- 关闭弹窗:关闭弹窗 -> 重置表单
- 确认:校验数据有效性 -> 更新数据 -> 关闭弹窗
- 弹窗编辑:编辑弹窗里的信息,只要不点击确认,下次进来还是原来的
总结下
- 1. 触发阶段:用户操作触发交互(按钮点击、表格行操作)
- 2. 数据准备阶段:可能需要拉取数据、填充表单、设置初始状态
- 3. 交互呈现阶段:UI 层显示(弹窗、表格)
- 4. 结果提交阶段:数据校验、数据更新、页面刷新、状态同步
- 5. 状态收敛阶段:关闭弹窗、刷新列表、回到初始状态
根据行为模型建立代码结构
有了上一步的经验,代码结构其实就清晰了很多,以vue3
举例
js
const baseData = {...}
const discountData = reactive(deepCLone(baseData)) // 真实数据,类比B端的表格项:tableData item
const discountFormData = reactive(deepCLone(baseData)) // 表单,类比B端的表单:formData
const isShowPopup = ref(false)
const showPopup = () => {
isShowPopup.value = true
Object.assign(discountFormData, deepClone(discountData))
}
const resetForm() = () => {
Object.assign(discountFormData, deepClone(baseData))
}
const hidePopup = () => {
isShowPopup.value = false
resetForm()
}
const confirmPopup = () => {
Object.assign(discountData, deepClone(discountFormData)) // 表单数据更新到真实数据里,类比B端其实就是去设置表格里的数据
hidePopup()
}
// 优惠计算逻辑略
这代码看上去就像是B端的弹窗设计了,从一开始的代码上找不着你发力点,到使用相同行为模型的代码逻辑,降低了心智负担等,而且职责也清晰
总结
- UI差异 ≠ 行为逻辑差异
- 每次开发时,可以询问自己,这个需求是否有类似的行为逻辑,可以通过日常积累,不断深化理解
- 每次开发时要进行需求分析 -> 行为模型建立 -> 代码结构确认 -> 代码细节优化等步骤,最关键的还是行为模型和代码结构确认
- 也可以通过阶段划分:触发,数据准备,交互呈现、结果提交、状态收敛