field list什么意思_从源码中学Vue(六)「解密」为什么操作数组的方法也会触发视图更新...
歡迎來到我的《從源碼中學Vue》專題系列文章,更多精彩內容持續更新中,歡迎關注 :)
上一章節我大概分析了下在Vue中的 Watcher、Observer、Dep三者的關系,以及如何檢測數據變化去更新視圖的,以及通過源碼分析了vue在初始化的時候是如何響應模板數據。
本章目標
- Object.defineProperty存在的問題
- 為什么在我們操作數組的時候可以實現視圖更新
- vue中數組劫持仍然存在的問題
Object.defineProperty存在的問題
我們都知道,在Vue2.x中,內部實現的數據響應是通過Object.defineProperty來實現的,其實這個API是存在一些問題的。
比如,它不能兼聽到數組的變化,什么意思呢?我來舉個例子。
我通過Object.defineProperty定義了一個簡單的方法,當我們的key為數組的時候,我們直接通過obj.list.push修改數組的時候,可以看到,我們的set方法并沒有被觸發。
我們再來通過vue來看下我們修改list的時候會發生什么?
可以看到,在vue中,我們對data下的list添加元素的時候,視圖被更新了,也就是說,vue中操作數組的時候會發生數據響應。
結論:原生的Object.defineProperty不能劫持數組push等操作,但是vue卻可以?
為什么在我們操作數組的時候可以實現視圖更新
那么說明Vue內部一定做了一些兼容處理!
帶著這個問題,跟我去源碼中找找答案吧!!
那么在數據劫持的目錄下很容易找到一個array.js的文件,我們打開它看看
文件目錄:node_modulesvuesrccoreobserverarray.js
它長這樣!
先不用細看,看到
這一坨代碼,我們就知道,vue針對這些方法做了處理。
那好,我們接下來具體分析下vue具體做了什么?
我們將原生的Array上的原型復制出來存儲到了arrayMethods變量中。之所以要復制一個原型對象出來,是不能響應原生的數組的特性。
這有一個def方法,我們去找下它的定義。
目錄:node_modulesvuesrccoreutillang.js
它就是給一個Object對象添加Object.defineProperty,然后主要看第二個參數。value,通過調用我們知道,我們傳入的實參是一個function 。
什么意思呢,這里我們就能夠兼聽到當數組的原生方法被觸發后的回調。我再舉個例子
這個示例中,我兼聽了原生數組的push方法,當有push操作的時候,可以觸發一個回調函數。
那么到這里,相信vue的數組響應原理應該就明白了吧。
到這里還沒完,我們接著往下看
我圈出來的是為了實現數組原生的方法的執行。這里面的this就是指向的我們的要兼聽的數據對象
在這個方法的最后,源碼調用了ob.dep.notify()方法,那么這個ob是怎么來的呢?
const ob = this.__ob__這個對象我們可以在Observer類的中找到。
我們給value定義了一個__ob__的屬性,然后賦值為this,這里面的this指向的是Observer對象。所以我們在最后可以調用ob.dep.notify()方法。
最后再來看這一坨代碼
定義了一個inserted變量,它表示的是是否為添加。我們知道,給數組添加元素的方法有三個,push,unshift,splice。然后調用Observer兼聽數組的observeArray方法。
splice這個方法當有第三參數的時候,可以視了給數組添加項。
思考一下,為什么要兼聽數組的添加的方法呢?
其實前面也有提到過。比如,我們添加數組的項可能為一個對象,或者數組,如果這是些那么我們的Observer將要繼續兼聽這個對象,給這個對象添加get和set方法。
舉個例子
當我們給數組添加成一個對象的時候,vue這時候也會劫持對象,我們可以看到對象的a已經被設置了get和set。
vue中數組劫持仍然存在的問題
在vue中,有一種情況下數組是不能被劫持的,那就是當我們手動通過索引改變數組的某一項的時候,不會觸發視圖的更新。比如這樣:
視圖并沒有變化
這個解決辦法就是重新給list賦值 ,我們知道數組的concat和slice方法都可以返回一個全新的數組。我們可以這樣做。
vm.list = vm.list.concat([]); 或者vm.list = vm.list.slice();到這里,Vue劫持數組的原理基本上就分享完了。
總結:
這里是暢哥聊技術 《從源碼中學Vue》系列文章,更多精彩內容持續更新中,敬請期待。
未完待續。。。
總結
以上是生活随笔為你收集整理的field list什么意思_从源码中学Vue(六)「解密」为什么操作数组的方法也会触发视图更新...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何将qmainwidget 客户区坐标
- 下一篇: apache http自动跳转https