<p>用 flex 布局实现响应式菜品网格:容器设 display: flex + flex-wrap: wrap,子项用 flex: 1 1 calc(33.333% - 16px),媒体查询中按屏调百分比;购物车仅存 id/name/price/count 四字段,增减时 stopPropagation,结算校验 item.count > 0 且 totalPrice > 0。</p>

用 flex 布局实现菜品网格,别碰 float 和 inline-block
现代点餐页的菜品列表必须响应式,小屏竖排、中屏两列、大屏三列——flex 是唯一靠谱选择。用 float 会触发 BFC 导致购物车高度塌陷;inline-block 的换行空格会吃掉宽度,导致第三列掉行。
实操建议:
- 容器设
display: flex+flex-wrap: wrap,子项用flex: 1 1 calc(33.333% - 16px)(留出间距) - 在媒体查询里改
calc()中的百分比:小屏用100%,平板用50% - 避免给菜品卡片设固定高度,用
min-height配合align-items: stretch保持底部价格对齐
localStorage 存购物车数据,但别直接存 DOM 节点或函数
刷新不丢购物车是基本体验,但很多人把 document.querySelector('.cart-item') 这种节点对象塞进 localStorage,结果报 TypeError: Converting circular structure to JSON——因为 DOM 节点含循环引用。
正确做法是只存纯数据结构:
立即学习“前端免费学习笔记(深入)”;
- 每条记录只保留
id、name、price、count四个字段 - 用
JSON.stringify()存,JSON.parse()取;存之前先Array.from(new Set(cart))去重 - 加减数量时,用
cart.find(item => item.id === id)找到后改count,别 push 新对象
点击「+」按钮时,event.stopPropagation() 防止误触卡片跳转
很多菜单页给整个菜品卡片绑了 click 事件跳详情页,但卡片里的「+」「−」按钮也响应 click——不阻止冒泡,点一次「+」就加完数量又跳走。
解决很简单:
- 所有增减按钮的事件监听器第一行写
event.stopPropagation() - 按钮用
button[type="button"],别用div或a,避免默认行为干扰 - 如果用了 Vue/React,用
@click.stop或onClick={(e) => { e.stopPropagation(); ... }}
结算按钮禁用状态要同时校验 cart.length 和 totalPrice > 0
用户清空购物车后可能手动改 localStorage,或并发操作导致前端状态滞后。只判断 cart.length === 0 不够——比如数组里还剩一个 {id: 1, count: 0} 的脏数据,length 是 1,但实际没东西可结。
安全写法:
- 禁用条件写成
!cart.some(item => item.count > 0) || totalPrice <= 0 - 每次修改购物车后,立刻调用一个
cleanCart()函数,过滤掉count <= 0的项 - 按钮文案别只写「去结算」,加上动态总价:
去结算(¥<span id="total-price">0.00</span>)
细节上最常被忽略的是「加购成功提示」的防重复触发:用户连点三次「+」,不能弹三个 Toast。得用节流或标记位控制,否则体验像卡顿。

















