vue中data為啥要用函數(shù)
理解為啥使用函數(shù)不直接使用對(duì)象的方式善榛,簡(jiǎn)單一句話戴而。直接對(duì)象會(huì)造成同一對(duì)象共享問(wèn)題。
為什么會(huì)造成共享問(wèn)題挽霉?
細(xì)探源碼防嗡,下面從組件的三個(gè)過(guò)程看看整個(gè)過(guò)程。
組件的三個(gè)過(guò)程
- 創(chuàng)建
- 注冊(cè)
- 實(shí)例化
下面這篇文章對(duì)VUE源碼有比較清晰的認(rèn)識(shí)https://blog.csdn.net/yolo0927/article/details/78242989
組件是如何使用的侠坎?
// 方式一
var MyComponent = Vue.extend({
name: 'my-component',
template: '<div>{{name}}</div>'蚁趁,
data(){
return{
name:""
}
}
});
Vue.component('my-component', MyComponent);
// 方式二
Vue.component('my-component', {
name: 'my-component',
template: '<div>{{name}}</div>',
data(){
return{
name:""
}
}
});
// 使用組件
<div id="example">
<my-component></my-component>
</div>
- 方式一是怎么處理data的硅蹦?
源碼位于global-api/extend.js
這里傳入的參數(shù)extendOptions和Super.options都一并合并放入的Sub.options,并通過(guò)this._init將原型上的options也并入Sub.options.extend最后返回的是這個(gè)構(gòu)造函數(shù)Sub荣德;
- 方式二怎么處理data的?
具體如何定位到component源碼的可以參考這篇文章的分析
https://segmentfault.com/a/1190000012004707
從上面可以看出童芹,component做的處理就是注冊(cè)這個(gè)創(chuàng)建的組件涮瞻,如果傳入的第二個(gè)參數(shù)是一個(gè)對(duì)象,則會(huì)進(jìn)行一次創(chuàng)建操作假褪,其實(shí)也就是內(nèi)部也會(huì)執(zhí)行一下extend操作署咽,然后在注冊(cè)。這里沒(méi)有涉及到data的操作,也沒(méi)有實(shí)例化這個(gè)組件宁否。這里的這個(gè)definition對(duì)象是一個(gè)Sub構(gòu)造函數(shù)窒升。
- 使用時(shí)怎么處理data的?
使用是組件實(shí)例化并完成了掛載過(guò)程慕匠。組件實(shí)例化也就是new一個(gè)構(gòu)造函數(shù)實(shí)例化饱须,掛載也就是將組件指定到HTML元素中輸出。new Sub則會(huì)實(shí)例化創(chuàng)建的這個(gè)組件台谊。
- 那么new過(guò)程data是怎么樣的呢蓉媳?
new內(nèi)部會(huì)創(chuàng)建一個(gè)新的空對(duì)象,然后將這個(gè)對(duì)象的原型指向這個(gè)構(gòu)造函數(shù)的原型锅铅,并復(fù)制構(gòu)造函數(shù)的屬性酪呻,然后返回這個(gè)新的對(duì)象。如下:
function myNew(constructor){
return function(){
let obj={};
obj.__proto__=constructor.prototype;
constructor.apply(obj, arguments);
return obj;
}
}
所以Sub.options是構(gòu)造函數(shù)的屬性盐须,最后會(huì)通過(guò)constructor.apply(obj, arguments);變成實(shí)例化對(duì)象的屬性玩荠。
一般的構(gòu)造函數(shù)實(shí)例化,屬性被共享的情況
function initData(data){
return typeof data==='function'?data():data;
}
function Sub(data){
this.data=initData(data);
}
let data={
name:'mzz'
}
let dataFn=function(){
return{
name:'mzz'
}
}
let obj1=new Sub(data),
obj2=new Sub(data);
console.log(obj1.data===obj2.data); //true
let obj3=new Sub(dataFn),
obj4=new Sub(dataFn);
console.log(obj3.data===obj4.data); //false
上面這個(gè)一般化類(lèi)實(shí)例對(duì)象結(jié)果對(duì)象屬性被所有實(shí)例對(duì)象共享贼邓,VUE采取data()而不是直接對(duì)象也是這個(gè)道理阶冈。
總結(jié)
js中對(duì)象的引用造成數(shù)據(jù)被共享問(wèn)題比較常見(jiàn),可以學(xué)習(xí)這里傳函數(shù)形式避免構(gòu)造函數(shù)的對(duì)象屬性被實(shí)力對(duì)象共享立帖。大家都知道的原型繼承原型會(huì)被所有實(shí)例對(duì)象共享眼溶,無(wú)論在原型上的屬性是對(duì)象還是一般數(shù)據(jù)類(lèi)型,通過(guò)這里的學(xué)習(xí)晓勇,也可以看到實(shí)例對(duì)象還會(huì)共享構(gòu)造函數(shù)的對(duì)象類(lèi)型屬性堂飞。
以上僅作為個(gè)人學(xué)習(xí)參考,如有錯(cuò)誤望批評(píng)指正绑咱;
如果有小伙伴再繼續(xù)深入绰筛,有新見(jiàn)解的,望賜教描融。