做了9年前端,web、app、桌面应用、小程序都做过,踩过的坑比写过的Bug还多。
今天挑10个最高频、最容易踩的坑分享出来,每个坑附完整代码和解决方案。建议收藏,迟早用得上。
坑1:浮点数精度——电商项目的噩梦
// 经典翻车现场
0.1 + 0.2 === 0.3 // false
// 实际项目中的坑
const price = 19.9
const qty = 3
console.log(price * qty) // 59.699999999999996
解决:金额场景统一用「分」为单位,整数运算。前端展示时 (amount / 100).toFixed(2)。
// 正确做法
const priceInCent = 1990
const total = priceInCent * 3 // 5970
const display = (total / 100).toFixed(2) // "59.70"
坑2:Vue3 reactive解构丢失响应式
// ❌ 响应式丢了
const state = reactive({ count: 0, name: 'test' })
const { count, name } = state // 普通变量,不再响应式
// ✅ 用toRefs
const { count, name } = toRefs(state)
// ✅ 更推荐直接用ref
const count = ref(0)
这个坑我亲眼见过3个项目踩了,页面不更新,排查半天,结果是解构问题。
坑3:useEffect依赖遗漏(React闭包陷阱)
// ❌ count永远是0
const [count, setCount] = useState(0)
useEffect(() => {
const timer = setInterval(() => {
console.log(count) // 闭包捕获了初始值0
}, 1000)
return () => clearInterval(timer)
}, []) // 空依赖
// ✅ 用函数式更新
useEffect(() => {
const timer = setInterval(() => {
setCount(prev => prev + 1)
}, 1000)
return () => clearInterval(timer)
}, [])
坑4:addEventListener不移除——内存泄漏
// ❌ 组件卸载后监听器还在
mounted() {
window.addEventListener('resize', this.handleResize)
}
// 忘了在destroyed/unmounted里移除
// ✅ Vue3正确做法
onMounted(() => {
window.addEventListener('resize', handleResize)
})
onUnmounted(() => {
window.removeEventListener('resize', handleResize)
})
一个项目里有5个组件各加了scroll监听不移除,页面越来越卡,排查了一下午。
坑5:flex布局下text-overflow失效
/* ❌ 省略号不生效 */
.flex-item {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* ✅ 加min-width: 0 */
.flex-item {
min-width: 0; /* flex子元素必须加这个 */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
这个坑不知道害了多少人,flex子元素默认min-width是auto,不会缩小到比内容小。
坑6:深拷贝的隐藏Bug
// ❌ JSON.parse(JSON.stringify()) 的坑
const obj = {
date: new Date(), // 变字符串
fn: () => {}, // 丢失
undef: undefined, // 丢失
reg: /test/, // 变空对象
}
// ✅ 用structuredClone(2022+原生支持)
const copy = structuredClone(obj)
// 注:函数仍然无法拷贝,需要手动处理
坑7:小程序setData传大数据——页面卡死
// ❌ 一次传500条列表数据
this.setData({ list: hugeArray })
// ✅ 分页加载 + 路径更新
this.setData({
[`list[${index}].status`]: 'done' // 只更新变化字段
})
setData是跨线程通信,数据量大直接卡死。做过一个电商小程序,首页列表300条商品,setData一次耗时200ms+,改成路径更新后降到3ms。
坑8:路由懒加载没做——首屏白屏5秒
// ❌ 同步导入所有页面
import Home from './pages/Home'
import User from './pages/User'
import Order from './pages/Order'
// ✅ 路由懒加载
const routes = [
{ path: '/', component: () => import('./pages/Home.vue') },
{ path: '/user', component: () => import('./pages/User.vue') },
]
一个后台项目30多个页面全同步加载,打包后vendor.js有2MB,首屏白屏5秒。加了懒加载后1.2秒。
坑9:环境变量泄露——密钥暴露在前端
// ❌ 把API密钥写在前端代码里
const API_KEY = 'sk-xxxxxxxxxx' // 打包后源码可见!
// ✅ Vite项目只有VITE_前缀的才暴露
// .env
VITE_API_URL=https://api.xxx.com // ✅ 可暴露
SECRET_KEY=sk-xxx // ✅ 不会暴露
见过一个项目把支付密钥写在前端config里,上线2天被薅了3万。
坑10:跨域问题——开发能用上线就挂
// ❌ 开发环境直连API
fetch('http://api.xxx.com/data')
// ✅ 开发用proxy,生产用nginx反向代理
// vite.config.js
server: {
proxy: {
'/api': {
target: 'http://api.xxx.com',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '')
}
}
}
每个前端新人都会踩一次跨域的坑,区别只是踩早踩晚。
总结
| 排名 | 坑点 | 严重度 |
|---|---|---|
| 1 | 浮点数精度 | ⭐⭐⭐⭐⭐ |
| 2 | Vue3响应式丢失 | ⭐⭐⭐⭐⭐ |
| 3 | useEffect闭包 | ⭐⭐⭐⭐⭐ |
| 4 | 事件监听泄漏 | ⭐⭐⭐⭐ |
| 5 | flex省略号失效 | ⭐⭐⭐⭐ |
| 6 | 深拷贝Bug | ⭐⭐⭐ |
| 7 | setData传大数据 | ⭐⭐⭐⭐⭐ |
| 8 | 首屏白屏 | ⭐⭐⭐⭐⭐ |
| 9 | 环境变量泄露 | ⭐⭐⭐⭐⭐ |
| 10 | 跨域问题 | ⭐⭐⭐⭐ |
这些坑我用9年经验帮你踩过了,收藏备用,遇到的时候能省你几个小时调试时间。
评论区说说你踩过最坑的前端Bug是什么?
我是前端老兵AI,9年+前端工程师,专注前端实战+AI编程提效
📦 加微信lxxs1203,备注"掘金",领取《前端+AI编程实战干货包》
🎬 更多实操视频 → B站搜索:前端老兵AI
📱 公众号搜索「前端老兵之AI」,持续更新深度技术文章