您好,登錄后才能下訂單哦!
本篇內容介紹了“Vue異步更新DOM及$nextTick執行機制源碼分析”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
我們知道,Vue實現響應式并不是數據發生變化之后DOM立即變化,而是按一定的策略進行DOM的更新。
Vue 在更新 DOM 時是異步執行的。只要偵聽到數據變化,Vue 將開啟一個隊列,并緩沖在同一事件循環中發生的所有數據變更。如果同一個 watcher 被多次觸發,只會被推入到隊列中一次。這種在緩沖時去除重復數據對于避免不必要的計算和 DOM 操作是非常重要的。然后,在下一個的事件循環 “tick" 中,Vue 刷新隊列并執行實際(已去重的)工作。
$nextTick會在DOM更新之后被觸發,以獲取最新DOM節點。
具體來講:我們使用 JavaScript 進行原生DOM操作時,隨著 JavaScript 代碼執行會同步進行DOM更新;而使用 Vue 則會異步更新 DOM,會在當前執行棧的最后更新DOM。
對于兼容的瀏覽器來說,nextTick相當于是微任務,即$nextTick的回調函數是在當前執行棧的所有同步任務執行完畢后再執行,所以nextTick中會得到 DOM 更新后的結果。(不過頁面渲染始終是在微任務執行之后才進行的,所以$nextTick回調函數執行時頁面還沒有進行渲染,回調函數執行時在頁面上看不到更新后的結果)
注:瀏覽器如果不兼容則有幾種備選方案,其中setTimeout是最后的一種備選方案,它會將回調函數加入任務隊列 task 中,等待執行。
JavaScript原生DOM操作(隨著JS代碼的執行同步進行DOM更新):
<body> <ul id="ul1"> <li>100</li> <li>200</li> <li>300</li> </ul> <script> const ul1 = document.getElementById('ul1') console.log(ul1.children.length); // 3 const newLi = document.createElement('li') newLi.innerHTML = '400' ul1.appendChild(newLi) console.log(ul1.children.length); // 4 Promise.resolve().then(() => { alert(ul1.children.length) // 彈出4,此時頁面還沒有進行渲染(頁面還未展示內容) }) </script> </body>
Vue異步更新DOM:
<template> <div id="app"> <ul ref="ul1"> <li v-for="(item, index) in list" :key="index"> {{ item }} </li> </ul> <button @click="addItem">添加一項</button> </div> </template> <script> export default { name: "app", data() { return { list: ["a", "b", "c"], }; }, methods: { addItem() { this.list.push(`${Date.now()}`); this.list.push(`${Date.now()}`); this.list.push(`${Date.now()}`); // 獲取 DOM 元素 const ulElem = this.$refs.ul1; // eslint-disable-next-line console.log(ulElem.childNodes.length);// 3 // 1. 異步進行 dom 更新,$nextTick 待 DOM 更新完再回調 // 2. dom 更新時會將 data 的修改做整合,多次 data 修改只會更新一次 this.$nextTick(() => { // eslint-disable-next-line console.log(ulElem.childNodes.length); // 6 alert(ulElem.childNodes.length); // 彈出 6,此時頁面還沒有進行渲染(頁面還沒展示新添加的3個元素) }); }, }, }; </script>
因為如果同步進行DOM更新,則每次對響應式數據進行修改就都會觸發setter -> 通知watcher -> 觸發re-render -> 生成new vnode(vdom) -> patch(更新真實DOM)。
如果每次修改數據都會走一遍這個流程是非常消耗性能的,所以使用異步更新 DOM 的策略,先對數據修改進行整合,再使用最終的整合結果一次性對 DOM 進行更新。
<template> <div> <button @click="callbackFun">點我展示輸入框并自動獲取焦點</button> <br /> <input type="text" v-show="test" ref="input" /> </div> </template> <script> export default { name: "App", data() { return { test: false, }; }, methods: { callbackFun() { this.test = true; this.$nextTick(function () { this.$refs.input.focus(); // 若該行代碼不放在 $nextTick 中,則無法展示輸入框后自動獲取焦點 }); }, }, }; </script>
“Vue異步更新DOM及$nextTick執行機制源碼分析”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。