首先说明,该标题并不是哗众取宠!!!
1. 起因
作者临近毕业,在筹备各种面试时,遇到了经常问的一个问题,data为什么必须是一个函数?我通过查询看了各种文章众说纷纭,没有一个讲明白,我印象最深的是以下这一篇。
data是放在原型对象上的,所以每个实例共用同一个data,因此需要使用函数,返回一个对象,大概是这样,原文在这(Vue组件为什么data必须是一个函数? - 掘金 (juejin.cn))
let Vue = function(){
}
// data 为对象的情况
Vue.prototype.data = {
name:'jack',
age:22
}
// data 为函数的情况
Vue.prototype.data = function(){
return {
name:'jack',
age:22
}
}
感兴趣的可以看下原文,虽然这样子好像可以说的通,所有实例都共用同一个原型对象中的data,因此如果 data 是一个函数的话,返回一个新的对象,解决了对象在实例中共享的问题。
但是这并不是真正在Vue中data为一个函数的原因。
2. 在我阅读源码后的体会
在我阅读源码之前,我一直把上述原理刻在脑子里,在寻找暑假实习的面试中,也把此当作实现原理同面试官讲述,所以现在想起来有些气愤。以下是Vue中部分源码实现,我将进行简化。
- data 为对象的情况
我们知道,vue 中组件是要复用的,每使用一次其实就是 new VueComponent(以下代码中写为 Vue) 一次,而每一个组件实例共用我们传入的同一个
options,对象本身是引用类型,自然每一个实例的data都指向同一块内存,因此对一个组件中的data数据做更改,其他组件中的data 一同改变,很显然这不是我们想要的效果。为了解决这个问题,便将data改为一个函数。
// 我们传入的 options
let options = {
data: {
name: '石头山'
}
}
let Vue = function(options){
this._data = options.data;
}
let vm1 = new Vue(options);
let vm2 = new Vue(options);
// 对 vm1 中的 data 进行更改
vm1._data.name = '挖掘机'
console.log(vm2._data.name); // 挖掘机
- data 为函数
改为函数后,我们利用返回值创建了一个对象,所以每一个组件实例中的
data不再指向同一块内存,所以不在共用。
// 我们传入的 options
let options = {
data(){
return {
name: '石头山'
}
}
}
let Vue = function(options){
this._data = options.data();
}
let vm1 = new Vue(options);
let vm2 = new Vue(options);
// 对 vm1 中的 data 进行更改
vm1._data.name = '挖掘机'
console.log(vm2._data.name); // 石头山
结论: 这个原理非常简单,并没有上文作者提到的原型链一说。但是必须明白组件在 Vue 中使用的原理,每一个组件其实就是对应着一个VueComponent构造函数的实例,根组件对应 Vue 构造函数的实例,而 VueComponent 又是继承于Vue。
3. 结尾
发表此文章我并不是想攻击上篇文章作者,我只是希望掘金的所有作者对自己发表的文章负责,因为有很多技术小白在寻找知识的道路上,他们说不定就翻阅了你的文章,并将你的结论,知识分享铭记于心,甚至在各种面试场合侃侃而谈,因此我希望每一位有经验的作者在发表文章前对自己的文章负责,对阅读你文章的所有小伙伴负责。
作者只是一个大三小白,提出自己的一些拙见,如有不对的地方,请大佬们指出。