搜尋
首頁web前端js教程Vue為什麼不能偵測陣列變動?原因如這些

問題描述:Vue偵測資料的變動是透過Object.defineProperty實現的,所以無法監聽陣列的新增操作是可以理解的,因為是在建構函式中就已經為所有屬性做了這個偵測綁定運算。

但官方的原文:由於JavaScript 的限制, Vue 無法偵測以下變動的陣列:

當你利用索引直接設定一個項目時,例如: vm.items[indexOfItem] = newValue
當你修改陣列的長度時,例如: vm.items.length = newLength

這句話是什麼意思?我測試了下Object.defineProperty是可以透過索引屬性來設定屬性的存取器屬性的,那為何做不了監聽?

有些論壇上的人說因為數組長度是可變的,即使長度為5,但是未必有索引4,我就想問問這個答案哪裡來的,修改length,新增的元素會被加到最後,它的值為undefined,透過索引一樣可以取得他們的值,怎麼就叫做「未必有索引4」了呢?

既然知道數組的長度為何不能遍歷所有元素並且透過索引這個屬性全部添加set和get不就可以同時更新視圖了嗎?

如果要說的話,考慮到效能的問題,假設元素內容只有4個有意義的值,但是長度確實1000,我們不可能為1000個元素做偵測操作。但是官方說的由於JS限制,我想知道這個限制是什麼內容?各位大大幫我解決下這個問題,感謝萬分



面對這個問題,我想說的是,首先,長度為1000,但只有4個元素的數組並不一定會影響效能,因為js中對資料的遍歷除了for迴圈還有forEach、map、filter、some等,除了for迴圈外(for,for...of),其他的遍歷都是對鍵值的遍歷,也就是除了那四個元素外的空位並不會進行遍歷,所以也就不會造成性能損耗,因為循環體中沒有操作的話,所帶來的性能影響可以忽略不計,下面是長度為10000,但只有兩個元素的陣列分別使用for及forEach遍歷的結果:

var arr = [1]; arr[10000] = 1
function a(){
    console.time()
    for(var i = 0;i<arr.length;i++)console.log(1)
    console.timeEnd()
}
a(); //default: 567.1669921875ms
a(); //default: 566.2451171875ms

function b(){
    console.time()
    arr.forEach(item=>{console.log(2)})
    console.timeEnd()
}
b(); //default: 0.81982421875ms
b(); //default: 0.434814453125ms

可以看到結果非常明顯,不過,如果for迴圈中不做操作的話兩者速度差不多

其次,我要說的是,我也不知道這個限制是什麼     (⇀‸↼‶)      ⠮( •́ω•̀ )╭

一個物件上定義一個新屬性,或修改一個物件的現有屬性, 並傳回這個物件。陣列的索引也是屬性,所以我們是可以監聽到陣列元素的變化的

var arr = [1,2,3,4]
arr.forEach((item,index)=>{
    Object.defineProperty(arr,index,{
        set:function(val){
            console.log(&#39;set&#39;)
            item = val
        },
        get:function(val){
            console.log(&#39;get&#39;)
            return item
        }
    })
})
arr[1]; // get  2
arr[1] = 1; // set  1

但是我們新增一個元素,就不會觸發監聽事件,因為這個新屬性我們並沒有監聽,刪除一個屬性也是。

再回到題主的問題,既然陣列是可以被監聽的,那為什麼vue不能偵測vm.items[indexOfItem] = newValue導致的陣列元素改變呢,就算這個下標所對應的元素是存在的,且被監聽了的?

為了搞清楚這個問題,我用vue的源碼測試了下,下面是vue對資料監測的源碼:
Vue為什麼不能偵測陣列變動?原因如這些

可以看到,當資料是數組時,會停止對資料屬性的監測,我們修改一下原始碼:
Vue為什麼不能偵測陣列變動?原因如這些

使資料為數組時,仍然監測其屬性,然後在defineReactive函數中的get,set列印一些東西,方便我們知道呼叫了get以及set。這裡加了個簡單判斷,只看數組元素的get,set
Vue為什麼不能偵測陣列變動?原因如這些

然後寫了一個簡單案例,主要測試使用vm.items[indexOfItem] = newValue改變陣列元素能不能被監控到,並且響應式的渲染頁面
Vue為什麼不能偵測陣列變動?原因如這些

運行頁面
Vue為什麼不能偵測陣列變動?原因如這些

可以看到,運行了6次get,我們數組長度為3,也就是說數組被遍歷了兩遍。兩遍不多,頁面渲染一次,可能多次觸發一個資料的監聽事件,就算這個資料只用了一次,具體的需要看尤大程式碼怎麼寫的。就拿這個來說,當監聽的資料為數組時,會運行dependArray函數(程式碼在上面圖中get的實作裡),這個函數裡對數組進行了遍歷取值操作,所以會多3遍get,這裡主要是vue對data中arr數組的監聽觸發了dependArray函數。

當我們點擊其中一個元素的時候,例如我點擊的是3
Vue為什麼不能偵測陣列變動?原因如這些

#

可以看到會先執行一次set,然後資料更新,重新渲染頁面,陣列又被遍歷了兩遍。

但是! ! !陣列確實變成響應式的了,也就是說js語法功能不會限制陣列的監控。

這裡我們是用長度為3的數組測試的,當我把數組長度增加到9時
Vue為什麼不能偵測陣列變動?原因如這些

可以看到,運行了18次get,數組還是被遍歷了兩遍,點擊某個元素同理,渲染的時候也是被遍歷兩次。
Vue為什麼不能偵測陣列變動?原因如這些

有了上面的實驗,我的結論是數組在vue中是可以實現響應式更新的,但是不明白尤大是出於什麼考慮,沒有加入這一功能,希望有知道的大佬們不吝賜教

相關文章:

vue中數組變化檢測問題

為什麼 返回的json無法 轉為陣列

相關影片:

陣列變動偵測-麥子學院Vue.js影片教學                 #               

以上是Vue為什麼不能偵測陣列變動?原因如這些的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
Python vs. JavaScript:開發人員的比較分析Python vs. JavaScript:開發人員的比較分析May 09, 2025 am 12:22 AM

Python和JavaScript的主要區別在於類型系統和應用場景。 1.Python使用動態類型,適合科學計算和數據分析。 2.JavaScript採用弱類型,廣泛用於前端和全棧開發。兩者在異步編程和性能優化上各有優勢,選擇時應根據項目需求決定。

Python vs. JavaScript:選擇合適的工具Python vs. JavaScript:選擇合適的工具May 08, 2025 am 12:10 AM

選擇Python還是JavaScript取決於項目類型:1)數據科學和自動化任務選擇Python;2)前端和全棧開發選擇JavaScript。 Python因其在數據處理和自動化方面的強大庫而備受青睞,而JavaScript則因其在網頁交互和全棧開發中的優勢而不可或缺。

Python和JavaScript:了解每個的優勢Python和JavaScript:了解每個的優勢May 06, 2025 am 12:15 AM

Python和JavaScript各有優勢,選擇取決於項目需求和個人偏好。 1.Python易學,語法簡潔,適用於數據科學和後端開發,但執行速度較慢。 2.JavaScript在前端開發中無處不在,異步編程能力強,Node.js使其適用於全棧開發,但語法可能複雜且易出錯。

JavaScript的核心:它是在C還是C上構建的?JavaScript的核心:它是在C還是C上構建的?May 05, 2025 am 12:07 AM

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript應用程序:從前端到後端JavaScript應用程序:從前端到後端May 04, 2025 am 12:12 AM

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

Python vs. JavaScript:您應該學到哪種語言?Python vs. JavaScript:您應該學到哪種語言?May 03, 2025 am 12:10 AM

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

JavaScript框架:為現代網絡開發提供動力JavaScript框架:為現代網絡開發提供動力May 02, 2025 am 12:04 AM

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

JavaScript,C和瀏覽器之間的關係JavaScript,C和瀏覽器之間的關係May 01, 2025 am 12:06 AM

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具