vue组件中为什么data是一个函数

218 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第25天,点击查看活动详情

组件可以访问Vue实例的数据吗?

在我们使用组件的时候,可以直接访问到Vue实例上面的数据吗?

我们在app.vue里声明一个数据msg,值为“v我50”,然后创建一个组件,在app.vue里引入并注册使用,然后在组件里直接使用app.vue的msg数据

//app.vue
<template>
  <div id="app">
    <component-a></component-a>
  </div>
</template>
export default {
  components: {
    componentA
  },
  name: 'App',
  data () {
    return {
      msg:'v我50'
    }
  }
}

//组件A,并在组件a里引用app实例的数据
<template>
  <div>
    <div>组件A</div>
    <div>{{msg}}</div>
  </div>
</template>

这样能访问成功吗?答案是不行的,控制台会报 “属性或方法‘msg’未在实例上定义,但在渲染过程中被引用” 的错误,所以得出组件不能直接访问vue实例中的数据的结论

所以Vue组件有自己保存数据的地方,组件是一个单独功能模块的封装,也应该有属于自己的数据,自己的数据放在那里呢?组件对象也有一个data属性(也有自己的methods等属性),只是这个data属性必须是一个函数,这个函数返回一个对象,里面才是保存着数据的地方

为什么data要是一个函数

首先看看data是一个函数的例子,创建组件a,在data里都声明一个变量count,每次点击按钮的时候count+1,然后在app.vue里都引入注册,并使用2次

//
//app.vue
<template>
  <div id="app">
    <component-a></component-a>
    <component-a></component-a>
  </div>
</template>

//组件a
<template>
  <div>
    <div>{{count}}</div>
    <button @click="count++">+1</button>
  </div>
</template>

可以看到很正常,没有什么bug,控制台也没有报错

3.gif

然后再试试将data改为一个对象:

data:{
    count:0
}

可以只看到控制套给我们报了一个错,告诉我们data必须是一个函数,而且连渲染都渲染不出来

图片.png

我们可以欺骗一下vue让它以为是一个函数,其实本质上还是一个对象

const data={
  count:0
}
export default {
  data(){
    return data
  }
}

重新运行之后发现控制台不报错了,数据也渲染出来了,但是当增加的时候,不止当前点击的组件的count会增加,其他组件也会增加

3.gif

这是为什么呢?这是因为如果2个组件用的data都是同一个对象,也就是2个数组操作的都是同一个对象,它们的内存地址是相同的,当改变组件里某一个数据的时候其他组件也会做出改变。当data是一个函数时,使用多次同样的组件会在函数的栈空间里创建一个新的对象并返回,它们的内存地址是完全不同的

相当于每个组件实例都有自己的作用域,那么局部作用域中的数据改变是不会影响其他作用域的,也就是说每个组件相互独立,互不影响