关键在于将数量合法性校验嵌入每步操作:add()/reduce()/setQuantity()统一入口并即时校验边界,UI按钮状态由canAdd()/canReduce()前置控制,输入失焦自动修正,库存变更时quantity超限则自动降级,异常路径按场景差异化响应。

关键不是在按钮点击时硬加 if 判断,而是把数量变更的合法性检查嵌入到每一次操作的执行路径里,让流程本身自然挡住越界行为。
加减操作必须走统一入口方法
不要直接修改 quantity 字段,所有变更都通过 add() 或 reduce() 方法触发。这些方法内部立刻校验边界,再决定是否执行:
- add() 先判断 quantity < stock,成立才 +1,否则不动作或返回 false
- reduce() 先判断 quantity > 0,成立才 −1;若减后为 0,可顺带触发删除逻辑
- 输入框直接设值时,用 setQuantity(target) 方法,内部调用 clamp(target, 0, stock),强制归入合法区间
UI 层响应要前置预判,而非事后拦截
按钮状态应由商品自身能力决定,而不是等用户点了再弹提示:
- “+”按钮是否可用,取决于 item.canAdd() —— 即 quantity < stock
- “−”按钮是否禁用,取决于 item.canReduce() —— 即 quantity > 0
- 输入框失焦时,自动将输入值过一遍 setQuantity(),非法值当场修正(如输 -2 → 变成 0,输 999 → 变成 stock)
流程中每个环节都要守住边界,不依赖上一环
边界控制不是某一层的责任,而是贯穿整个操作链:
- 用户点击“+” → 触发 item.add() → 内部校验 → 成功则更新 UI,失败则静默或 toast 提示
- 后台返回库存变更 → 调用 item.updateStock(newStock) → 若当前 quantity > newStock,则自动降为 newStock,并同步通知 UI
- 清空购物车 → 先对每个 item 调用 reduce() 直至为 0,再移除;避免直接 cart = {} 绕过商品实例逻辑
异常路径也要有明确流向
当流程遇到越界时,不同场景选择不同响应方式,不能全靠 console.warn 或忽略:
- UI 操作越界:返回 false 或 null,由调用方决定提示语(如“库存不足”“不能再少了”)
- 批量导入数据:解析后逐条过 clampQuantity,脏值自动修正,不中断整体流程
- 结算前校验:遍历所有 item,若任一 quantity ≠ clamp(quantity, 0, stock),拒绝下单并高亮问题项

















