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

Vue中如何结合@input正确处理watch()监听逻辑?

Vue中v-model与@input执行顺序导致的watch触发问题

我需要基于@input触发的变量更新来处理v-model的变化,但遇到了Vue执行顺序的问题。以下是简化后的代码:

<script setup>
import { ref, watch } from 'vue'

const foo = ref(1)
const bar = ref(1)
const lorem = ref(false)

const handleInput = (val) => {
  bar.value = val
}

watch(foo, (newFoo) => {
  if (bar.value === 2) {
    lorem.value = true
  }
})
</script>

<template>
  <input v-model="foo" @input="handleInput(2)"><br>
  {{foo}}<br>
  {{bar}}<br>
  {{lorem}}
</template>

实际表现是:watch监听器会在handleInput方法执行前就触发。修改输入框的foo值时,只有第二次修改foo,lorem的值才会被设为true,但我希望它能立刻变为true。

我试过用nextTick()和flush: 'post'配置,但都没得到预期结果:

<script setup>
import { ref, nextTick, watch } from 'vue'

const foo = ref(1)
const bar = ref(1)
const lorem = ref(false)

const handleInput = (val) => {
  nextTick(() => {
    bar.value = val
  })
}

watch(foo, async (newFoo) => {
  await nextTick()
  if (bar.value === 2) {
    lorem.value = true
  }
}, { flush: 'post' })
</script>

<template>
  <input v-model="foo" @input="handleInput(2)"><br>
  {{foo}}<br>
  {{bar}}<br>
  {{lorem}}
</template>

解决方案

问题出在Vue的执行顺序上:v-model是语法糖,它会在@input事件触发后更新绑定的响应式变量,但默认情况下,watch会在响应式变量更新后立即执行,这时候@input的回调还没跑完,bar的值还没被修改,所以watch里的判断不成立。

下面是两种可行的解决方法:

方法一:调整watch的触发时机

给watch加上flush: 'post'配置,让它在所有同步更新完成后再执行,此时handleInput已经修改了bar的值:

<script setup>
import { ref, watch } from 'vue'

const foo = ref(1)
const bar = ref(1)
const lorem = ref(false)

const handleInput = (val) => {
  bar.value = val // 直接赋值,不用套nextTick
}

watch(foo, (newFoo) => {
  if (bar.value === 2) {
    lorem.value = true
  }
}, { flush: 'post' }) // 关键:post模式延迟watch触发
</script>

<template>
  <input v-model="foo" @input="handleInput(2)"><br>
  {{foo}}<br>
  {{bar}}<br>
  {{lorem}}
</template>

方法二:直接在handleInput中处理逻辑

既然逻辑依赖于@input触发的bar更新,不如把watch里的判断直接移到handleInput里,彻底避开执行顺序问题:

<script setup>
import { ref } from 'vue'

const foo = ref(1)
const bar = ref(1)
const lorem = ref(false)

const handleInput = (val) => {
  bar.value = val
  // 直接在这里判断赋值
  if (bar.value === 2) {
    lorem.value = true
  }
}
</script>

<template>
  <input v-model="foo" @input="handleInput(2)"><br>
  {{foo}}<br>
  {{bar}}<br>
  {{lorem}}
</template>

两种方法都能实现修改foo时lorem立刻变为true的效果,按需选择即可。

内容的提问来源于stack exchange,提问作者DirkReuter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 19:57:32