Vue
的時候須要在建立Vue實例時傳入一個
option
,這裏包含了咱們定義的
props、methods、data
等。而在
methods
的方法中獲取
data
中的
key
值都是直接經過
this.key
獲取
option
對象中的
methods
中的定義的方法如何經過
this
訪問到data中的數據呢?
let vue = new Vue({
el: '#app',
methods: {
say() {
console.log(this.msg)
}
},
data: {
msg: 'jjjjj'
}
})
複製代碼
一開始我想是將data
和methods
中的數據全都掛載到了vm
上,然而Vue
實例上有methods
中定義的方法,卻沒有data
中的屬性,data中的數據所有存儲在vm._data中,經過this.key
訪問實際上是this._data.key
,Vue
在這裏作了一層代理,經過defineProperty
設置了vm的getter和setter,而methods中的方法在initMethods方法中將其中的this
綁定到了vm
上,這樣methods中方法訪問的this
也就指向了_data
。
javascript
下面是參照源碼相關邏輯的簡化代碼:vue
function MyVue (option) {
this._init(option)
}
MyVue.prototype._init = function (option) {
const vm = this
vm.$options = option // 源碼在此作了對子組件option的合併處理
if (vm.$options.methods) initMethods(vm, vm.$options.methods) // 源碼中還有對props的處理,data、props、methods都會作查重處理,不能有相同的屬性名
if (vm.$options.data) initData(vm)
}
function initMethods (vm, methods) {
const props = vm.$options.props
for (const key in methods) {
vm[key] = methods[key].bind(vm) // 將methods上的方法掛載到vm上並將方法中全部的this指向vm,經過下面的proxy就能夠訪問到_data上的屬性
}
}
function initData (vm) { // 將data上數據複製到_data並遍歷全部屬性添加代理
vm._data = vm.$options.data
const keys = Object.keys(vm._data)
let i = keys.length
while (i--) {
const key = keys[i]
proxy(vm, `_data`, key)
}
}
function proxy (target, sourceKey, key) {
let sharedPropertyDefinition = {}
sharedPropertyDefinition.get = function proxyGetter () {
return this[sourceKey][key]
}
sharedPropertyDefinition.set = function proxySetter (val) {
this[sourceKey][key] = val
}
Object.defineProperty(target, key, sharedPropertyDefinition) // 一層代理,每次訪問this[key]時代理到this._data[key]
}
let app = new MyVue({
methods: {
say: function () {
console.log(this.msg + this.age)
}
},
data: {
msg: 'jjj',
age: 33
}
})
app.say() // jjj33
複製代碼