大家好,我是 輝夜真是太可愛啦 。這是我最近在寫的【手把手教你搓Vue響應式原理】系列,本文將一步步地為你解開vue響應式原理的面紗。由于本人也是在寫這篇文章的過程中不斷試錯,不斷學習改進的,所以,本文同樣很適合和我一樣的初學者。和
Vue的設計理念如出一轍,那就是漸進增強。
MVVM
在講這個之前,首先要明白一點,這個所謂的響應式,其實本身就是對 MVVM 的理解。
MVVM 其實就是所謂的 Modal View ViewModal。
簡單理解,就是你的 data 中的數(shù)據(jù),和 template 模板中的界面,本身就是兩個東西。
但是, Vue 給你做了一層中間的 ViewModal,讓視圖上的改變能反映到 data 中, data 中的改變能反映到視圖上。

在這個反映過程中,ViewModal就是視圖和數(shù)據(jù)的一個橋梁。
非侵入式和侵入式
同樣是讓 a + 1 。
在Vue 中,這個橋梁是你看不見的,因為 Vue 都幫你完成了視圖和數(shù)據(jù)的變化傳遞。
而 React 就是侵入式的,因為要顯式地聲明 setState ,通過它,來設置變量的同時,設置視圖的改變。

所以,所謂的侵入式,其實就是對于橋梁的侵入。
Vue的神奇之處
所以, Vue 的神奇之處就在于,不需要我們手動地顯示調(diào)用 setState ,也就是這個橋梁, Vue 已經(jīng)幫我們橋接上了。
要讓 data 改變的同時,視圖也發(fā)生改變,所以,問題的所在,就是我們需要監(jiān)聽,什么時候,這個變量發(fā)生了變量。
然而, ES5 中,就有那么一個特性,可以做到對于數(shù)據(jù)的劫持(監(jiān)聽)。
它就是 Object.defineProperty 。
Object.defineProperty
Object.defineProperty( obj, prop, descriptor ) 方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現(xiàn)有屬性,并返回此對象,與此同時,它可以對對象的一些額外底層的屬性進行設置。例如可以設置writable , enumerable , configurable 等屬性。
后面的額外屬性設置,才是我們使用它的重點。
但是,我們使用的不是上面的幾個屬性,最主要的還是它的 get set ,可以對屬性值的獲取和設置操作進行攔截。
-
get
get主要是可以對值的獲取進行攔截,,它必須要傳入一個 return ,并且,該函數(shù)的返回值會被用作屬性的值。我們可以來看一個例子:

let a={name:'jack'};
Object.defineProperty(a,'name',{
get(){
return '你已經(jīng)被攔截了!';
},
})
console.log(a.name); //你已經(jīng)被攔截了!
由于設置了 get ,所以,輸出 a.name 的時候直接會被攔截,走 get() 中的 return 所以,此時,a.name 的值應該是 你已經(jīng)被攔截了!。
-
set
set主要是可以對值的設置進行攔截,該方法會接受一個參數(shù),那就是被賦予的新值。我們可以來看一個例子:
let a={name:'jack'};
Object.defineProperty(a,'name',{
set(newValue){
console.log('你正在設置值' + newValue);
}
})
a.name='bob'; // 你正在設置值bob
由于設置了 set ,所以,設置值的時候會被攔截,走 set() 中的方法。
文末總結
所以, Vue 能自動獲取data中的改變,反映到視圖的原因,就是有對于變量的獲取和設置的劫持,當變量發(fā)生改變的同時, Vue 能在第一時間知道,并且對視圖做出相應的改變操作。
而這把鑰匙就是 Object.defineProperty 。