對于初學Vue.js的小伙伴而言,可能會認為Vue實例是一個很神奇的東西捧韵!因為它除了幫助我們完成雙向綁定之外丝蹭,還在某些細節(jié)方面為我們增加了一些理解上面的小煩惱!希望通過這篇文章能夠為勤勉的你解惑~
看一段簡單代碼先:
new Vue({
el:"#myApp",
data:{
userName:"laoWangTou",
age:16
},
methods:{
run(){
// 輸出結果:laoWangTou今年16歲了
console.log(this.userName+"今年"+this.age+"歲了");
}
},
created(){
// this為什么可以調用methods的run方法犁享?
this.run();
}
})
對于以上代碼可能會有兩個小疑問:
1余素、為什么鉤子函數(shù)中的 this.run 可以調用到methods對像下的方法run?
2、為什么methods對象下的run方法可以通過this獲得data下的屬性炊昆?
要弄明白這兩個問題首先你要明白下面幾個點:
- this即是通過Vue生成的實例vm
const vm = new Vue({
el:"#myApp",
created(){
console.log(vm === this);// true
}
})
- $data與data是相等的
const data ={};
const vm = new Vue({
el:"#myApp",
data,
created(){
console.log(this.$data === data);// true
}
})
console.log(vm.$data === data);// true
- $data的屬性被修改桨吊,vm實例下的屬性也會發(fā)生相應的變化
const vm = new Vue({
el:"#myApp",
data:{
userName:"laoWangTou",
age:16
},
created(){
this.$data.userName = "xiaoZhang"
this.$data.age = 18;
// 輸出結果:xiaoZhang今年18歲了
console.log(this.userName+"今年"+this.age+"歲了");
}
})
// 輸出結果:xiaoZhang今年18歲了
console.log(vm.userName+"今年"+vm.age+"歲了");
通過之前的兩個疑問及得到的個結論,咱們可以先來個小猜測:
1凤巨、通過Vue生成的實例中有一屬性為$data视乐,其值為接收對象的data值
2、vm實例中代理了data的屬性
3敢茁、methods下的方法賦值給了vm實例
于是佑淀,結合Vue.js的源碼模擬出了以下較易理解的代碼:
// 定義了一個構造函數(shù)
function Vue(options) {
this.$data = options.data || {};
this.initState(options);
}
Vue.prototype.initState = function (opts) {
if(opts.data)
this.initData(opts.data);
if(opts.methods)
this.initMethods(opts.methods);
if(opts.created)
opts.created.call(this);
}
Vue.prototype.initData = function (data) {
var keys = Object.keys(data);
var i = keys.length;
while (i--){
const key = keys[i];
this.proxy("$data",key);
}
}
Vue.prototype.initMethods = function (methods) {
for (var key in methods) {
this[key] = methods[key];
}
}
Vue.prototype.proxy =function(sourceKey, key) {
Object.defineProperty(this, key, {
get() {
return this[sourceKey][key]
},
set(val){
this[sourceKey][key] = val;
}
});
};
驗證:
const vm = new Vue({
el:"#myApp",
data:{
userName:"laoWangTou",
age:16
},
methods:{
run(){
// 輸出結果:laoWangTou今年16歲了
console.log(this.userName+"今年"+this.age+"歲了");
}
},
created(){
// this為什么可以調用methods的run方法?
this.run();
}
});
// 輸出結果:laoWangTou今年16歲了
console.log(vm.userName+"今年"+vm.age+"歲了");
—————END—————
喜歡本文的朋友們彰檬,歡迎關注公眾號 張培躍伸刃,收看更多精彩內容