Vue中v-model与@keydown同元素时数据更新延迟问题咨询
Vue中v-model与keydown事件不同步问题的原理与解决
原理:事件触发顺序导致的延迟
keydown事件是在键盘按下瞬间触发的,此时浏览器还没来得及更新输入框的DOM值,而v-model的同步逻辑依赖输入框的DOM值变化(基于input/change等事件)。所以当keydown事件执行时,v-model绑定的ticker数据还没同步到最新输入内容,自然会少最后一个字符。
举个例子:输入"something"的最后一个"g"时,keydown先触发,此时输入框的实际值还停留在"somethin",v-model还没把新的"g"同步到ticker里,所以打印出来的就是少一个字符的结果。
解决办法
1. 替换keydown为input事件
input事件是在输入框内容更新完成后触发的,刚好能和v-model的同步节奏匹配,直接修改事件绑定即可:
<input v-model="ticker" @keydown.enter="addClick($event)" @input="getNames" >
这样每次输入内容变化时,getNames拿到的ticker都是最新的。
2. 在keydown中直接取输入框实时值
如果必须保留keydown事件,可以通过事件对象直接获取输入框当前的DOM值,跳过v-model的同步延迟:
<input v-model="ticker" @keydown.enter="addClick($event)" @keydown="getNames($event)" >
getNames(event) { // 直接从输入框DOM元素拿最新值 const currentVal = event.target.value; console.log(currentVal); let filtered = this.coinNames.filter(item => item.toUpperCase().startsWith(currentVal.toUpperCase())) console.log(filtered); return filtered; }
3. 用nextTick/setTimeout延迟执行
利用JavaScript的事件循环机制,让代码在DOM更新(v-model同步完成)后再执行:
方式一:Vue的$nextTick
getNames() { this.$nextTick(() => { console.log(this.ticker); let filtered = this.coinNames.filter(item => item.toUpperCase().startsWith(this.ticker.toUpperCase())) console.log(filtered); return filtered; }); }
方式二:setTimeout(0延迟即可)
getNames() { setTimeout(() => { console.log(this.ticker); let filtered = this.coinNames.filter(item => item.toUpperCase().startsWith(this.ticker.toUpperCase())) console.log(filtered); return filtered; }, 0); }
内容的提问来源于stack exchange,提问作者fetixzz
相关产品推荐
相关产品推荐

