一、定義[nextTick、事件循環]
nextTick的由來:
由於VUE的數據驅動視圖更新,是異步的,即修改數據的當下,視圖不會立刻更新,而是等同一事件循環中的所有數據變化完成之后,再統一進行視圖更新。
nextTick的觸發時機:
在同一事件循環中的數據變化后,DOM完成更新,立即執行nextTick(callback)內的回調。
應用場景:
需要在視圖更新之后,基於新的視圖進行操作。
以上出現了事件循環的概念,其涉及到JS的運行機制,包括主線程的執行棧、異步隊列、異步API、事件循環的協作,此處不展開之后再總結。大致理解:主線程完成同步環境執行,查詢任務隊列,提取隊首的任務,放入主線程中執行;執行完畢,再重復該操作,該過程稱為事件循環。而主線程的每次讀取任務隊列操作,是一個事件循環的開始。異步callback不可能處在同一事件循環中。
簡單總結事件循環:
同步代碼執行 -> 查找異步隊列,推入執行棧,執行callback1[事件循環1] ->查找異步隊列,推入執行棧,執行callback2[事件循環2]...
即每個異步callback,最終都會形成自己獨立的一個事件循環。
結合nextTick的由來,可以推出每個事件循環中,nextTick觸發的時機:
同一事件循環中的代碼執行完畢 -> DOM 更新 -> nextTick callback觸發
tips:本文的任務隊列、消息隊列、異步隊列指同一個東西,均指macrotask queue。
上面這些內容純屬是從網上搬運過來的,接下來說說在項目中遇到的問題
還是用文字啰嗦點說吧!代碼實在不好展示我想表現的,因為我認為這種問題會在其他地方還會有類似問題;
項目中用到了bootstrap-select.js插件(帶搜索功能的下拉框),類似這樣的插件在vue渲染完數據后肯定需要初始化,大概如下
mounted: function () { $('#select').selectpicker(); }
我的業務需求是上面還有一個下拉框需要先選擇上面的,來決定下面顯示哪個模塊,這時問題就來了,數據發生改變了,我的下拉框就變成如下圖
然后我很機智呀!果斷去watch里面再初始化一下插件呀!但是發現無效,這下徹底懵逼了,后面經過各種打印,各種百度發現了這個東東
watch:{ type: function (val, oldVal) { if(val==2){ Vue.nextTick(function () { //或者用 this.$nextTick $('#select').selectpicker(); })
} } }
最后總結:只怪自己太菜了,js基礎不夠NB,什么都不想說了,努力吧!