小編給大家分享一下Vue不能檢測數(shù)組變動(dòng)的原因是什么,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
站在用戶的角度思考問題,與客戶深入溝通,找到盈江網(wǎng)站設(shè)計(jì)與盈江網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:網(wǎng)站設(shè)計(jì)制作、網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、主機(jī)域名、網(wǎng)絡(luò)空間、企業(yè)郵箱。業(yè)務(wù)覆蓋盈江地區(qū)。問題來源:https://segmentfault.com/q/1010000015780995
問題描述:Vue檢測數(shù)據(jù)的變動(dòng)是通過Object.defineProperty實(shí)現(xiàn)的,所以無法監(jiān)聽數(shù)組的添加操作是可以理解的,因?yàn)槭窃跇?gòu)造函數(shù)中就已經(jīng)為所有屬性做了這個(gè)檢測綁定操作。
但是官方的原文:由于 JavaScript 的限制, Vue 不能檢測以下變動(dòng)的數(shù)組:
當(dāng)你利用索引直接設(shè)置一個(gè)項(xiàng)時(shí),例如: vm.items[indexOfItem] = newValue
當(dāng)你修改數(shù)組的長度時(shí),例如: vm.items.length = newLength
這句話是什么意思?我測試了下Object.defineProperty是可以通過索引屬性來設(shè)置屬性的訪問器屬性的,那為何做不了監(jiān)聽?
有些論壇上的人說因?yàn)閿?shù)組長度是可變的,即使長度為5,但是未必有索引4,我就想問問這個(gè)答案哪里來的,修改length,新增的元素會(huì)被添加到最后,它的值為undefined,通過索引一樣可以獲取他們的值,怎么就叫做“未必有索引4”了呢?
既然知道數(shù)組的長度為何不能遍歷所有元素并通過索引這個(gè)屬性全部添加set和get不就可以同時(shí)更新視圖了嗎?
如果非要說的話,考慮到性能的問題,假設(shè)元素內(nèi)容只有4個(gè)有意義的值,但是長度確實(shí)1000,我們不可能為1000個(gè)元素做檢測操作。但是官方說的由于JS限制,我想知道這個(gè)限制是什么內(nèi)容?各位大大幫我解決下這個(gè)問題,感謝萬分
面對這個(gè)問題,我想說的是,首先,長度為1000,但只有4個(gè)元素的數(shù)組并不一定會(huì)影響性能,因?yàn)閖s中對數(shù)據(jù)的遍歷除了for循環(huán)還有forEach、map、filter、some等,除了for循環(huán)外(for,for...of),其他的遍歷都是對鍵值的遍歷,也就是除了那四個(gè)元素外的空位并不會(huì)進(jìn)行遍歷(執(zhí)行回調(diào)),所以也就不會(huì)造成性能損耗,因?yàn)檠h(huán)體中沒有操作的話,所帶來的性能影響可以忽略不計(jì),下面是長度為10000,但只有兩個(gè)元素的數(shù)組分別使用for及forEach遍歷的結(jié)果:
var arr = [1]; arr[10000] = 1 function a(){ console.time() for(var i = 0;i{console.log(2)}) console.timeEnd() } b(); //default: 0.81982421875ms b(); //default: 0.434814453125ms
可以看到結(jié)果非常明顯,不過,如果for循環(huán)中不做操作的話兩者速度差不多
其次,我要說的是,我也不知道這個(gè)限制是什么 (????) ╮( ??ω?? )╭
Object.defineProperty() 方法會(huì)直接在一個(gè)對象上定義一個(gè)新屬性,或者修改一個(gè)對象的現(xiàn)有屬性, 并返回這個(gè)對象。數(shù)組的索引也是屬性,所以我們是可以監(jiān)聽到數(shù)組元素的變化的
var arr = [1,2,3,4] arr.forEach((item,index)=>{ Object.defineProperty(arr,index,{ set:function(val){ console.log('set') item = val }, get:function(val){ console.log('get') return item } }) }) arr[1]; // get 2 arr[1] = 1; // set 1
但是我們新增一個(gè)元素,就不會(huì)觸發(fā)監(jiān)聽事件,因?yàn)檫@個(gè)新屬性我們并沒有監(jiān)聽,刪除一個(gè)屬性也是。
再回到題主的問題,既然數(shù)組是可以被監(jiān)聽的,那為什么vue不能檢測vm.items[indexOfItem] = newValue
導(dǎo)致的數(shù)組元素改變呢,哪怕這個(gè)下標(biāo)所對應(yīng)的元素是存在的,且被監(jiān)聽了的?
為了搞清楚這個(gè)問題,我用vue的源碼測試了下,下面是vue對數(shù)據(jù)監(jiān)測的源碼:
可以看到,當(dāng)數(shù)據(jù)是數(shù)組時(shí),會(huì)停止對數(shù)據(jù)屬性的監(jiān)測,我們修改一下源碼:
使數(shù)據(jù)為數(shù)組時(shí),依然監(jiān)測其屬性,然后在defineReactive函數(shù)中的get,set打印一些東西,方便我們知道調(diào)用了get以及set。這里加了個(gè)簡單判斷,只看數(shù)組元素的get,set
然后寫了一個(gè)簡單案例,主要測試使用vm.items[indexOfItem] = newValue
改變數(shù)組元素能不能被監(jiān)測到,并響應(yīng)式的渲染頁面
運(yùn)行頁面
可以看到,運(yùn)行了6次get,我們數(shù)組長度為3,也就是說數(shù)組被遍歷了兩遍。兩遍不多,頁面渲染一次,可能多次觸發(fā)一個(gè)數(shù)據(jù)的監(jiān)聽事件,哪怕這個(gè)數(shù)據(jù)只用了一次,具體的需要看尤大代碼怎么寫的。就拿這個(gè)來說,當(dāng)監(jiān)聽的數(shù)據(jù)為數(shù)組時(shí),會(huì)運(yùn)行dependArray函數(shù)(代碼在上面圖中g(shù)et的實(shí)現(xiàn)里),這個(gè)函數(shù)里對數(shù)組進(jìn)行了遍歷取值操作,所以會(huì)多3遍get,這里主要是vue對data中arr數(shù)組的監(jiān)聽觸發(fā)了dependArray函數(shù)。
當(dāng)我們點(diǎn)擊其中一個(gè)元素的時(shí)候,比如我點(diǎn)擊的是3
可以看到會(huì)先運(yùn)行一次set,然后數(shù)據(jù)更新,重新渲染頁面,數(shù)組又是被遍歷了兩遍。
但是?。。?shù)組確實(shí)變成響應(yīng)式的了,也就是說js語法功能并不會(huì)限制數(shù)組的監(jiān)測。
這里我們是用長度為3的數(shù)組測試的,當(dāng)我把數(shù)組長度增加到9時(shí)
可以看到,運(yùn)行了18次get,數(shù)組還是被遍歷了兩遍,點(diǎn)擊某個(gè)元素同理,渲染的時(shí)候也是被遍歷兩次。
有了上面的實(shí)驗(yàn),我的結(jié)論是數(shù)組在vue中是可以實(shí)現(xiàn)響應(yīng)式更新的,但是不明白尤大是出于什么考慮,沒有加入這一功能,希望有知道的大佬們不吝賜教
2018-07-27補(bǔ)充
github上提問了尤大
以上是“Vue不能檢測數(shù)組變動(dòng)的原因是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊頻道!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。