Vue中如何在blur事件中检测触发失焦的按键?
解决Vue输入框blur与keyup事件顺序冲突及获取blur事件对象的问题
首先,你遇到的tab键触发时revertOriginalAmount先执行的问题,本质是浏览器事件执行顺序导致的:按下tab键时,浏览器会先把焦点从当前输入框移走(触发blur),之后才会触发keyup事件,所以saveValue总是晚一步,拿到的是已经回滚后的原始值。
另外,关于在@blur中获取原生事件对象的方法,Vue提供了特殊变量$event,只要在绑定方法时显式传递它,就能在方法里拿到事件对象。
下面给你两个可行的解决方案:
方案1:切换到keydown事件处理tab/enter(推荐)
keydown事件的触发时机在焦点变化(blur)之前,把@keyup.enter和@keyup.tab改成@keydown.enter和@keydown.tab,就能让saveValue先执行,从根源上解决顺序问题。
修改后的模板:
<input type="text" v-model="abcdef.amount" @keyup.esc="cancelChange()" @keydown.enter="saveValue(abcdef)" @keydown.tab="saveValue(abcdef)" @focus="saveOriginalAmount(abcdef)" @blur="revertOriginalAmount(abcdef, $event)">
对应的方法实现:
methods: { cancelChange() { this.revertOriginalAmount(this.abcdef); }, saveValue(obj) { // 执行你的保存逻辑,比如更新原始值或提交数据 obj.originalAmount = obj.amount; // 添加标记,告诉blur方法已经执行过保存,无需回滚 obj._isSaved = true; }, saveOriginalAmount(obj) { // 保存输入框的初始值 obj.originalAmount = obj.amount; // 重置保存标记 obj._isSaved = false; }, revertOriginalAmount(obj, event) { // 只有未保存的情况下才执行回滚 if (!obj._isSaved) { obj.amount = obj.originalAmount; } // 重置标记,避免影响下一次输入操作 obj._isSaved = false; // 这里可以使用event对象做额外判断,比如查看焦点移到了哪个元素 // console.log('焦点转移到:', event.relatedTarget); } }
方案2:通过标记+事件对象判断blur触发原因
如果你坚持使用keyup事件,可以通过给数据对象添加保存标记,结合blur事件对象的relatedTarget属性判断是否是tab切换导致的blur,不过这种方式不如方案1可靠(比如点击空白处时relatedTarget会为null)。
核心思路是:在keyup.tab执行saveValue时标记已保存,blur时检查标记,若已保存则不回滚。
关键代码调整:
<!-- 模板还是用keyup.tab --> <input type="text" v-model="abcdef.amount" @keyup.esc="cancelChange()" @keyup.enter="saveValue(abcdef)" @keyup.tab="saveValue(abcdef)" @focus="saveOriginalAmount(abcdef)" @blur="revertOriginalAmount(abcdef, $event)">
saveValue(obj) { obj.originalAmount = obj.amount; obj._isSaved = true; // 延迟重置标记,确保blur能读到 setTimeout(() => { obj._isSaved = false; }, 100); }, revertOriginalAmount(obj, event) { // 如果是tab切换到其他元素且已保存,不回滚 if (!obj._isSaved && !event.relatedTarget) { obj.amount = obj.originalAmount; } }
最后再强调一下:Vue中如果需要在事件绑定中同时传递自定义参数和原生事件对象,必须显式传入$event,否则方法无法获取到事件对象。比如@blur="revertOriginalAmount(abcdef, $event)",方法的第二个参数就是原生的Event实例。
内容的提问来源于stack exchange,提问作者Jun
相关产品推荐
相关产品推荐

