VueJS方法中setTimeout优先级异常,求助实现预期执行顺序
问题
我正在开发一个WhatsApp网页版的视觉与行为模拟器,需求是按下回车键发送消息后,延迟1秒再在聊天框显示消息。我尝试通过以下代码实现:
VueJS 代码
sentMessage(i){ const newMessage = this.text; this.text = ""; setTimeout(() =>{ this.contacts[this.currentContactChat].messages.push( { date: "10/01/2020 15:50:00", message: newMessage, status: "sent", }); }, 1000); },
HTML 代码
<div class="input-group"> <input type="text" class="form-control border border-start-0" placeholder="Scrivi un messaggio" aria-label="Username" aria-describedby="basic-addon1" v-model="text" @keyup.enter="sentMessage(i)"> </div>
预期执行顺序
- 通过
const newMessage = this.text获取输入框内容; this.text = ""立即清空输入框;- 等待1秒后,将新消息推入聊天消息数组,在聊天框显示。
实际执行顺序
- 获取消息内容;
- 启动定时器,等待1秒后,同时清空输入框并推入消息数组。
整个方法仿佛被setTimeout接管优先级,导致执行顺序异常。请问如何修正以实现预期的执行顺序?
解决方案
你的代码逻辑本身没问题,出现异常的核心原因是Vue的响应式更新是异步的:当你修改this.text = ""时,Vue不会立即更新DOM,而是将该更新任务放入异步队列。而setTimeout的回调同样属于异步任务,两者可能被浏览器在同一轮事件循环中处理,导致你视觉上误以为是同时执行。
要实现预期顺序,只需确保输入框的DOM更新完成后,再启动1秒定时器执行消息推入操作,可通过Vue的nextTick方法实现:
Vue 2 修正代码
sentMessage(i){ const newMessage = this.text; this.text = ""; this.$nextTick(() => { setTimeout(() =>{ this.contacts[this.currentContactChat].messages.push( { date: "10/01/2020 15:50:00", message: newMessage, status: "sent", }); }, 1000); }); },
Vue 3 修正代码
需先导入nextTick:
import { nextTick } from 'vue'; // ... sentMessage(i){ const newMessage = this.text; this.text = ""; nextTick(() => { setTimeout(() =>{ this.contacts[this.currentContactChat].messages.push( { date: "10/01/2020 15:50:00", message: newMessage, status: "sent", }); }, 1000); }); },
原理说明
nextTick会在Vue完成当前所有DOM更新后执行回调函数,这就保证了输入框已经被清空,之后再启动1秒定时器,就能严格按照预期顺序执行:获取内容→清空输入框→等待1秒→显示消息。
内容的提问来源于stack exchange,提问作者Pyrux
相关产品推荐
相关产品推荐

