Cosen95 / fe_interview

字节、阿里、美团、滴滴、腾讯等大厂高级前端面试题整理
238 stars 25 forks source link

Vue组件中的data为什么是个函数? #102

Open Cosen95 opened 4 years ago

Cosen95 commented 4 years ago

其实这个问题还有下半句:而 new Vue 实例里,data 可以直接是一个对象?

先来看下平时在组件和new Vue时使用data的场景:

// 组件
data() {
  return {
      msg: "hello 森林",
  }
}

// new Vue
new Vue({
  data: {
    msg: 'hello jack-cool'
  },
  el: '#app',
  router,
  template: '<App/>',
  components: {
    App
  }
})

我们知道,Vue组件其实就是一个Vue实例。

JS中的实例是通过构造函数来创建的,每个构造函数可以new出很多个实例,那么每个实例都会继承原型上的方法或属性。

Vuedata数据其实是Vue原型上的属性,数据存在于内存当中

Vue为了保证每个实例上的data数据的独立性,规定了必须使用函数,而不是对象。

因为使用对象的话,每个实例(组件)上使用的data数据是相互影响的,这当然就不是我们想要的了。对象是对于内存地址的引用,直接定义个对象的话组件之间都会使用这个对象,这样会造成组件之间数据相互影响。

我们来看个示例:

// 创建一个简单的构建函数
var MyComponent = function() {
    // ...
}
// 原型链对象上设置data数据,data设为Object
MyComponent.prototype.data = {
  name: '森林',
  age: 20,
}
// 创建两个实例:春娇,志明
var chunjiao = new MyComponent()
var zhiming = new MyComponent()
// 默认状态下春娇和志明的年龄一样
console.log(chunjiao.data.age === zhiming.data.age) // true
// 改变春娇的年龄
chunjiao.data.age = 25;
// 打印志明的年龄,发现因为改变了春娇的年龄,结果造成志明的年龄也变了
console.log(chunjiao.data.age)// 25
console.log(zhiming.data.age) // 25

使用函数后,使用的是data()函数,data()函数中的this指向的是当前实例本身,就不会相互影响了。

总结一下,就是:

组件中的data是一个函数的原因在于:同一个组件被复用多次,会创建多个实例。这些实例用的是同一个构造函数,如果 data 是一个对象的话。那么所有组件都共享了同一个对象。为了保证组件的数据独立性要求每个组件必须通过 data 函数返回一个对象作为组件的状态。

new Vue 的实例,是不会被复用的,因此不存在引用对象的问题。