1 回答

TA貢獻1876條經驗 獲得超5個贊
是這樣的,你console.log一下跟vue綁在一起的data里面屬性,你會發現那些打印出來多了兩個東西:
setter
getter
沒錯,vue檢測數組變動靠的就是這兩個屬性
而這兩個屬性,根據vue文檔的說法,它是使用了js原生的Object.defineProperty()
(其實準確來講應該是es的東西)
簡單地講,就是js屬性的屬性。。。怎么那么別扭。。。就是描述Array或者Json等Object類型里面的值的屬性,比如一個arr=[1,2,3,4]
,屬性的屬性就是里面的1具有的屬性。。。而且還有兩個:數據屬性和訪問器屬性。
比如數據屬性中的 Enumberable,如果它為false,那么即使它描述的那個屬性存在于json里面,也不會被for-in遍歷到。
好,回到正題,也就是vue對數組的檢測方法
它使用是Object類型底層的訪問器屬性來檢測數組變動的。
訪問器屬性存在兩個方法(姑且叫做方法吧,原文是叫attribute,但翻譯成屬性的話感覺太亂了。。而它們的作用又如同面向對象里面的方法一樣)
Get :在讀取時調用的函數。默認值為undefined
Set :在寫入時調用的函數,默認值為undefined
Vue的數組檢測變動就基于上面這兩個方法。
然而,都說了是es底層定義的東西,js是不可能直接就修改訪問上面的Get和Set,必須通過Object.defineProperty這個方法進行修改:
var json={ a:1 }; /*當json.a變動時打印修改信息*/ Object.defineProperty(json,'a',{ set:function(newValue){ console.log(this.value+'->'+newValue) }, get:function(){ console.log(this.value) } })
據說,第一個實現Object.defineProperty方法的瀏覽器是IE8,想不到吧,渣渣IE居然是第一個實現的。。。這也是為什么vuejs不支持ie8以下的垃圾ie了的原因了。
而且,vue為了檢測push這些操作造成的數組變動,都是將這些Api重新封裝了一遍的。。。
所以當你直接 vm.items[0]={}
這樣的時候,vue根本沒法給你做一個Object.defineProperty處理,自然也搞不出setter和getter,自然無法檢測數組變動。。。
添加回答
舉報