You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:53:57