寫文章不容易,點個讚唄兄弟 專一 Vue 源碼分享,文章分爲白話版和 源碼版,白話版助於理解工做原理,源碼版助於瞭解內部詳情,讓咱們一塊兒學習吧 研究基於 Vue版本 【2.5.17】javascript
若是你以爲排版難看,請點擊 下面連接 或者 拉到 下面關注公衆號也能夠吧java
寫這篇文章,我就是爲了記錄我對 Data 的一個疑問的探索,很簡短學習
data 的數據是怎麼能夠經過實例直接訪問的?this
第一想法,或許是,遍歷逐個複製?3d
可是其實並非,這裏涉及的一個詞,叫 【代理】代理
怎麼代理呢?聽我慢慢說,抓住逐個疑問,跟着我慢慢探索code
<br>對象
<br>blog
實例使用 initData 初始化數據,以下
function initData(vm) { var data = vm.$options.data; var keys = Object.keys(data); var i = keys.length; data = vm._data = ( typeof data === 'function' ? data.call(vm) : data ) || {}; while (i--) { var key = keys[i]; if (只要不是_和$開頭的屬性) { proxy(vm, "_data", key); } } }
首先,拿到 data 數據,若是data 是函數,就執行拿到返回值,不然直接拿設置的對象data
第二,保存data 數據
源碼中你能夠看到,把 data 保存到實例上了
vm._data = typeof data === 'function' ? data.call(vm) : data
初始化數據,是爲了拿到數據,而後放到存到實例上,做爲代理總部
<br>
<br>
接下來,就放大招了,到了【data 代理】 的重點了,看上面的源碼最後
會遍歷data對象,若是屬性名不是 【_ 或者 $】 開頭的話,就會被設置代理
至於爲何避開那兩個開頭的屬性?
Vue官網也說明了
剩下的其餘屬性,會被設置代理,如今咱們來看設置代理的那句話
proxy(vm,"_data",key)
proxy 是什麼?不要急,等我放上源碼
function proxy(target, sourceKey, key) { Object.defineProperty(target, key, { get() { return this[sourceKey][key] }, set(val) { this[sourceKey][key] = val; } }); }
明白嗎?經過 Object.defineProperty 設置 get 和 set 函數,來達到代理,移花接木的過程
可能這麼看不太直觀,我以一個屬性爲例寫清楚點
因而就會設置成這樣
下面是給 _data 屬性設置響應式的簡化代碼
這樣的做用,有四個
一、能夠直接經過 vm 訪問到name
簡化寫法,你看看 React 這個比,訪問 state,須要 http://this.state.xxx 寫多一層 很麻煩啊,Vue 作了一層代理就很好,可是呢,成本會大一些
二、保證數據統一
若是是開篇想的那樣,逐個賦值,數據改變的時候,就要同時維護兩份啊,簡直是地獄啊。可是 methods 的處理是直接複製到實例上的
三、不影響依賴收集
當訪問 【vm.name】,觸發代理 【vm.name 設置的get】,就會訪問 【vm._data.name】 ,從而觸發總部 【vm._data.name 設置的get】,這個get 用來依賴收集。最後徹底不會影響
四、不影響依賴更新
賦值 【vm.name】,觸發代理 【vm.name 設置的 set】,就會直接賦值給總部 【vm._data.name】 ,從而觸發 【vm._data.name 設置的set 】,這個set,用來依賴更新。最後徹底不會影響