为什么vue中data必须是一个函数
类比引用数据类型
Object是引用数据类型,如果不用function 返回,每个组件的data 都是内存的同一个地址,一个数据改变了其他也改变了;
javascipt只有函数构成作用域(注意理解作用域,只有函数的{}构成作用域,对象的{}以及if(){}都不构成作用域),data是一个函数时,每个组件实例都有自己的作用域,每个实例相互独立,不会相互影响
如果 data 是个对象,那么整个vue实例将共享一份数据,也就是各个组件实例间可以随意修改其他组件的任意值,这就有坑了【原型继承的槽点:指向相同,所有实例都会改变】。
- 但是 data 定义成一个函数,将会 return 出一个唯一的对象,不会和其他组件共享一个对象。
我们注册组件的时候实际上是建立了一个组件构造器的引用,只有使用组件的时候才会真正创建一个组件实例。
- 指向同一个对象/属性问题
function Person () {}
Person.prototype.data = {
a:1,
b:2
}
let p1 = new Person();
let p2 = new Person();
p1.data.a= 'A';
console.log(p2.data.a); // 'A'
- 解决:每一个实例化Vue组件对象下都有一个单独的data方法
function Person2 () {
this.data = this.data();
}
Person2.prototype.data = function () {
return {
a: 1,
b: 2
}
}
let p4 = new Person2();
let p5 = new Person2();
p4.data.a = 'A';
console.log(p5.data.a); // 1
Vue源码:
function initData (vm: Component) {
let data = vm.$options.data
data = vm._data = typeof data === 'function' ? getData(data, vm): data || {}
}
export function getData (data: Function, vm: Component): any {
pushTarget()
try {
return data.call(vm, vm)
} catch (e) {
handleError(e, vm, `data()`)
return {}
} finally {
popTarget()
}
}