最近畢設碰到的一個問題
我向dom中添加一個節(jié)點栽烂,然后使?jié)L動條滾動到底部
很簡單的一個需求,但是做的時候發(fā)現(xiàn)上遥,window.scrollTo(0,dom.scrollHeight)
并沒有像想象中一樣使?jié)L動條底部纯命,而節(jié)點的確已經添加進去了。
原因:瀏覽器加載機制js在css之前损俭,當添加節(jié)點的js執(zhí)行之后蛙奖,節(jié)點并沒有立即添加到頁面,因為還有同步的js代碼沒有執(zhí)行杆兵,js線程阻塞了GUI渲染線程雁仲,所以當執(zhí)行window.scrollTo
的時候,并沒有跳到頁面底部琐脏。
解決方法:將調到底部的window.scrollTo(0,dom.scrollHeight)
設為異步執(zhí)行攒砖,異步執(zhí)行的函數(shù)不會阻塞線程,而是等待所有同步代碼執(zhí)行完畢后日裙,才開始異步隊列函數(shù)的執(zhí)行吹艇,因此通過setTimeout(fn,0)
,當vue中diff算法(需要時間昂拂,并且在跳轉之前并未完成受神,vue使用的就是nexttick,在settimeout之前執(zhí)行)操作格侯,瀏覽器渲染完畢后鼻听,主線程空出才會執(zhí)行該跳轉代碼。
Vue是異步執(zhí)行dom更新的联四,一旦觀察到數(shù)據變化撑碴,Vue就會開啟一個隊列,然后把在同一個事件循環(huán) (event loop) 當中觀察到數(shù)據變化的 watcher 推送進這個隊列,所以數(shù)據變更后想要立即操作dom朝墩,需要把操作寫在同一個隊列的異步操作中醉拓,或者寫在下一個Vue.nextTick()中。
在node中還存在
process.nextTick
/setImmediate
控制代碼在事件隊列中的執(zhí)行鱼辙,執(zhí)行順序為
執(zhí)行隊列--->process.nextTick(fn)--->setTimeout ~= setlmmediate
廉嚼。