为什么vue的data必须是函数

1,254 阅读2分钟

这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战

问题

如果你正在写或者写过vue的组件,应该对组件下面的data不陌生,官方要求组件的data必须是函数。如果你使用的是对象,则控制台会报错。

export default {
  data: {
    name: '答案cp3'
  },
  mounted () {
    console.log(this.name)
  }
}

image.png

报错而且打印的name是undefined

export default {
  data () {
    return {
      name: '答案cp3'
    }
  },
  mounted () {
    console.log(this.name)
  }
}

image.png

为什么vue要对data限制为函数?

因为vue的组件是会复用的,如果你的data是对象的话,你在其中一个组件修改了data的值,另外一个组件获取到的data是修改后的值,并不是初始值。这样就不能保证组件的data数据的唯一性。

而如果你的data是函数的话,data函数执行后返回的是初始值,并不会受到影响。

下面通过一个模拟例子来说明:

模拟data是对象的情况:

const data = {i: 0} 
class Component {
  constructor () {
     this.data = data        
  }
  add () {
    this.data.i++
  } 
  show() {
   console.log(this.data.i)
  }
}
const componentA = new Component()
const componentB = new Component()
const componentC = new Component()

componentA.add()
componentB.add()

console.log(componentC.show()) // 2

模拟data是函数的情况:

const data = () => {return {i: 0}}
class Component {
  constructor () {
     this.data = data()       
  }
  add () {
    this.data.i++
  } 
  show() {
   console.log(this.data.i)
  }
}
const componentA = new Component()
const componentB = new Component()
const componentC = new Component()

componentA.add()
componentB.add()

console.log(componentC.show()) // 0

可以看到

第一个受到了新建实例的影响,输出了叠加后的值。

第二个就没有受到影响,还是保持原始值。

额外补充

上面说的是组件的data定义的时候必须是函数类型,但是在根实例并不会有这个限制,它可以是对象类型。

  <div id="app">
    {{msg}}
  </div>
  <script>
    const vm = new Vue({
      el: '#app',
      data: {
        msg: 'hello world'
      }
    })
    console.log(vm)
  </script>

这是因为vue中根实例是不会被复用的,只有组件才会被复用,所以根实例不会有这种情况。

在vue3中,不论是根实例还是组件, data都已经限制必须是函数了。