Vue.js中阻止两次事件触发:回车与blur事件重复执行问题
搞定Vue里Enter和Blur重复触发保存的小问题
嘿,这个坑我之前也踩过!按下回车时输入框自动失焦,导致keyup.enter和blur接连触发,同一个方法跑两次确实烦人。给你几个简洁又优雅的Vue风格解法,不用写一堆繁琐的DOM操作:
方案1:防抖函数一键解决(最省心)
直接给你的保存方法套一层防抖,短时间内多次调用只执行最后一次。如果项目里已经用了Lodash,那一行代码就能搞定:
methods: { // 用100ms延迟的防抖包装原方法 save_renamed_group: _.debounce(function(g) { // 这里写你的保存逻辑 console.log('保存分组:', g) }, 100), }
要是不想引入Lodash,自己写个极简版防抖也很简单:
// 先定义防抖工具函数 function debounce(func, delay = 100) { let timer; return function(...args) { clearTimeout(timer); timer = setTimeout(() => func.apply(this, args), delay); } } // 然后在组件methods里用 methods: { save_renamed_group: debounce(function(g) { // 保存逻辑 }) }
不管是blur还是enter触发,100ms内只会执行一次,完美避免重复调用,而且改动最小。
方案2:用状态变量精准控制
在组件里加个小标记,判断是否已经触发过保存,不让方法重复执行:
<template> <input @keyup.enter="handleSave(g)" @blur="handleSave(g)" > </template> <script> export default { data() { return { isSaving: false // 标记是否正在保存 } }, methods: { handleSave(g) { if (this.isSaving) return; // 如果正在保存,直接返回 this.isSaving = true; // 执行保存逻辑 this.save_renamed_group(g) // 如果是异步操作(比如调用API),记得在完成后重置标记 .finally(() => { this.isSaving = false; }); // 要是同步逻辑,直接执行后重置就行: // this.save_renamed_group(g); // this.isSaving = false; }, save_renamed_group(g) { // 你的保存代码,异步的话返回Promise console.log('保存分组:', g); // return axios.post('/api/save-group', { group: g }); } } } </script>
这个方案适合需要严格控制执行时机的场景,确保同一时间只有一次保存操作在跑。
方案3:利用事件顺序做拦截
按下Enter时,keyup.enter会比blur先触发,我们可以设置一个临时标记,让Blur事件在Enter触发后跳过执行:
<template> <input @keyup.enter="() => { isEnterTriggered = true; save_renamed_group(g); }" @blur="() => { if (!isEnterTriggered) save_renamed_group(g); isEnterTriggered = false; // 重置标记 }" > </template> <script> export default { data() { return { isEnterTriggered: false } }, methods: { save_renamed_group(g) { // 保存逻辑 } } } </script>
这个逻辑很直观,只需要一个临时变量,改动也很小,适合同步执行的保存场景。
这几个方案都符合Vue的组件化思路,没有多余的DOM操作,应该能满足你想要的“简洁优雅”~
内容的提问来源于stack exchange,提问作者user2950593
相关产品推荐
相关产品推荐

