學習Vue有一段時間了,有粉絲問我,Vue的資料代理與資料劫持到底是什么意思呢?這個程序到底發生了什么呢?今天我就來詳細解釋一下,
目錄
一、基礎知識
二、資料代理
1、含義
2、原理
3、好處
三、資料劫持
1. 定義
2.vue原理
一、基礎知識
我們先看 Object.defineProperty()的用法:
Object.defineProperty(obj,prop,descriptor)
引數介紹:
obj:目標物件
prop:需要定義的屬性或者方法的名字
descriptor:prop屬性所具有的特性
可供定義的特性串列:
value :屬性的值
writable:若為false,表示屬性值不能重寫
get:一旦目標屬性被訪問,則自動呼叫該方法,并回傳該方法的呼叫結果
set:一旦目標屬性被賦值,則自動呼叫該方法,進行賦值操作
configurable:若為false,則任何嘗試洗掉目標屬性,或修改目標屬性的
以下特性:writable、configurable、enumerable的行為均無效
enumerable:若為true,則可以在for ... in 回圈或Object.keys()可以列舉出來
二、資料代理
1、含義
通過一個物件,代理對另一個物件的操作,即:讀、寫操作,
2、原理
每個 Vue 應用都是通過用 Vue 函式創建一個新的 Vue 實體開始的:
var vm = new Vue({
// 選項options(配置項)
})
// 資料data物件
var data = { a: 1 }
// 該data物件被加入到一個 Vue 實體中
var vm = new Vue({
data: data
})
上面的代碼一般寫成下面的形式:也就是直接在Vue函式中,傳入 data 配置物件
const vm = new MVVM({
el: "#root",
data: {
a: 1
}
})
資料代理的實質是:
1. 利用 Object.defineProperty() 方法,給new出來的Vue實體 vm ,添加和 data 配置項中一模一樣的屬性和值,
2. 為每一個添加到 vm 上的屬性,都指定一個 getter/setter
3. 在 getter/setter 內部去操作(讀/寫)data 中對應的屬性
我們可以在控制臺列印 vm ,如下圖

可以看到,每一個屬性,都有一對 get/set 或 getter/setter方法,這是實作回應式變化的關鍵,
資料代理用到的Vue建構式偽代碼如下:
function MVVM(options){
// 將選項物件保存到vm
this.$options = options
// 將data物件保存到 vm和 新定義的data變數中
var data = this._data = this.$options.data
// 將vm保存在me變數
var me = this
// 遍歷data中所有屬性名
Object.keys(data).forEach(function (key){
// 每次遍歷,實作當前屬性的代理
me._proxy(key)
})
// 對data進行監視
observe(data,this)
// 創建一個用來編譯模板的compile物件,用來決議模板以及模板里的指令
this.$compile = new Compile(options.el || document.body, this)
}
MVVM.prototype = {
$watch:function(key,cb,options){
new Watcher(this,key,cb)
},
// 呼叫_proxy方法,對指定的屬性實作代理
// _proxy方法接收一個引數key,即原data物件中每個可列舉的屬性的屬性名
_proxy:function(key){
// 將vm保存在me變數
var me = this
// 給vm添加指定屬性名的屬性
Object.defineProperty(me,key,{
configurable:false, //不能再重新定義該屬性
enumerable:true, //可以列舉
// 使用vm.name的形式讀取屬性值時,自動呼叫get/getter回呼函式
get:function proxyGetter(){
return me._data[key]
},
// 使用vm.name = 'XXX'形式,寫操作時,自動呼叫set/setter回呼函式
set:function proxySetter(newValue){
me._data[key] = newValue
}
})
}
}
在 new 一個 Vue 實體的時候,會呼叫上面的建構式 MVVM :
建構式 MVVM 會接收到一個選項物件 options (也叫配置物件),也就是我們上面說的 new Vue 里面的選項物件
{
el: "#root",
data: {
a: 1
}
}
接收到 options 之后,保存在 this.$options 中,然后將data物件中的屬性賦值給 this._data ,為了實作回應式, vm 會對自身 data (注意,這是 vm 自己的 data )進行修改,也就是通過Object.defineProperty()給每一個屬性添加上 getter 和 setter 方法,
表面上,我們是在操作 vm.xxx ,實際上,我們操作的是 vm._data.xxx ,也就是 Vue 選項物件中的 data ,這就是資料代理的本質,
vm的_data中,不只是簡單的選項物件中的data

尚硅谷的 Vue 全家桶課程講解的很棒,我這里粘貼了他們的資料代理圖示:
3、好處
使用資料代理,之后我們使用 vm ,訪問 Vue 函式中 data 的屬性時,直接 this.a 就可以了,不需要使用 this.data.a ,注意,這里的 this,指向的是 vm
三、資料劫持
1. 定義
在上面的資料代理講解中,我們用到了 Object.defineProperty()方法,在每次對屬性進行代理時,訪問或者設定物件屬性值的時候,總要觸發 get 或 set 函式,回傳需要的值或設定相應屬性的值,那么,我們可以在觸發函式的時候,動一點手腳,做我們自己想做的事情,這就是“資料劫持”操作,
2.vue原理
Vue的資料劫持,實戰就是通過Object.defineProperty()方法來劫持物件屬性的getter和setter操作,并安裝一個監聽器,既可以監聽物件,又可以監聽陣列,當資料發生變化時,就發出通知,
Vue 是采用資料劫持結合發布者-訂閱者模式的方式,通過 Object.defineProperty()來劫持各個屬性的 getter 和 setter 方法,在資料變動時發布訊息給訂閱者,觸發相應的監聽回呼,實作回應式系統,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/413468.html
標籤:其他
上一篇:風尚云網:小程式-=>{組件/components應用篇}
下一篇:閉包和this指向問題
