本文介绍一种不依赖 css `pointer-events`、也不滥用 `preventdefault` 的 vue 原生方案,通过状态控制 + 动态事件绑定,安全实现链接点击节流(每 1500ms
最多响应一次)。
在 Vue 开发中,常需限制用户对按钮或链接的高频点击(如防止重复提交、避免路由快速跳转冲突)。但直接在 @click 中使用 setTimeout(() => e.preventDefault(), 1500) 是无效的——因为 e.preventDefault() 必须在事件同步执行阶段调用,延迟后调用已失去意义,且无法撤回已发生的导航行为。
✅ 正确思路是:提前拦截,而非事后阻止。即在点击瞬间判断是否允许触发,仅当未被“阻塞”时才启用 click 事件。
{{ item.name }}
? 注意::event 是 的 prop(Vue Router 3/4 均支持),用于显式指定响应的事件类型。传入空数组 [] 表示禁用所有原生事件(包括 click),从而彻底避免触发。
对应逻辑:
export default {
data() {
return {
isBlocked: false
}
},
methods: {
// 在 router-link 的 to 目标跳转前调用(推荐配合 @click.native 或自定义封装)
// 更稳妥的做法:改用普通 `` + 手动编程式导航
handleLinkClick() {
if (this.isBlocked) return;
this.isBlocked = true;
// 立即触发导航(或执行其他业务逻辑)
this.$router.push(this.item.path).catch(() => {}); // 避免导航守卫中断报错
// 1500ms 后恢复可点击状态
setTimeout(() => {
this.isBlocked = false;
}, 1500);
}
}
}若需保持
{{ item.name }}
methods: {
handleLinkClick() {
if (this.isBlocked) return;
this.isBlocked = true;
// 执行导航(支持 Vue Router 3/4)
this.$router.push(this.item.path).catch(err => {
console.warn('Navigation cancelled or failed:', err);
});
// 重置状态(注意:此处 setTimeout 不影响导航,仅控制 UI 可交互性)
setTimeout(() => {
this.isBlocked = false;
}, 1500);
}
}通过状态驱动 + 主动控制事件绑定或导航时机,你既能保障用户体验(视觉反馈可配合 :class="{ disabled: isBlocked }"),又能确保逻辑健壮、无竞态风险。