浅谈vue中的data与_data的关系是什么
在 Vue 实例中,data
属性是用户定义的用于存储数据的对象,而 _data
是 Vue 内部用于存储数据的对象。它们之间的关系是 Vue 实例的 data
属性实际上是对 _data
的代理。
当你在创建 Vue 实例时,Vue 会将用户定义的 data
属性与内部的 _data
对象建立关联,并在代理过程中添加一些访问和观察的逻辑。这样,你在访问 Vue 实例中的数据时实际上是在访问 _data
中的数据。
下面是一个简单的示例:
<div id="app"> <p>{{ message }}</p> </div> <script> const app = new Vue({ el: '#app', data: { message: 'Hello Vue!' } }); console.log(app._data.message); // 这里访问的是内部的 _data 对象的数据 </script>
在这个示例中,app.data
是用户定义的数据,而 app._data
是 Vue 内部存储数据的对象。message
属性实际上是通过代理从 app._data
中取得的。
需要注意的是,直接访问 _data
不是 Vue 推荐的做法,因为 Vue 提供了更高级的 API 来访问和操作数据,如计算属性、观察属性等。直接操作 _data
可能绕过 Vue 的响应式系统,导致数据不被正确地追踪和更新。
下面是一个实例,直接修改数组中第一个元素对象的值。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>更新时的一个问题</title> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <!-- 准备好一个容器--> <div id="root"> <h2>人员列表</h2> <button @click="updateMei">更新马冬梅的信息</button> <ul> <li v-for="(p,index) of persons" :key="p.id"> {{p.name}}-{{p.age}}-{{p.sex}} </li> </ul> </div> <script type="text/javascript"> Vue.config.productionTip = false const vm = new Vue({ el:'#root', data:{ persons:[ {id:'001',name:'马冬梅',age:30,sex:'女'}, {id:'002',name:'周冬雨',age:31,sex:'女'}, {id:'003',name:'周杰伦',age:18,sex:'男'}, {id:'004',name:'温兆伦',age:19,sex:'男'} ] }, methods: { //注意vm是vue实例vm._data.student =vm.student ,原理vue的数据代理,把vm中的属性代理到了_data updateMei(){ // this.persons[0].name = '马老师' //奏效 // this.persons[0].age = 50 //奏效 // this.persons[0].sex = '男' //奏效 // this.persons[0] = {id:'001',name:'马老师',age:50,sex:'男'} //失效 Vue.set(this.persons, 0, {id:'001',name:'马老师',age:50,sex:'男'})//奏效 this.persons.splice(0,1,{id:'001',name:'马老师',age:50,sex:'男'})//奏效 } } }) </script> </html>
上面案例直接修改数组的第一个元素会失效,原因是Vue把data
封装为_data
时做了响应式处理(代理),给所有的属性都加了get和set,类似于Object.defineProperty, 但是这里的直接通过索引整个赋值并不会做响应式处理(不会把data
数据代理到_data
),也就导致并不会实际修改_data,也就是vue的实际数据,除非使用Vue.set做响应式设值。
Vue在实现响应式数据时,会使用一些特殊的技巧来监听对象的属性变化,但这些技巧对数组的处理比较复杂。Vue能够检测到通过索引直接修改数组元素的情况,因为Vue会拦截数组的变异方法(例如 push
、pop
、shift
、unshift
、splice
和 sort
),从而能够在这些方法执行时触发视图更新。
然而,直接通过索引赋值的方式修改数组元素this.persons[0] = {id:'001',name:'马老师',age:50,sex:'男'}
,绕过了 Vue 的代理,Vue 无法检测到这样的变化,因此不会触发视图更新。
this.persons[0].name = '马老师'
这种方式可以生效的原因是因为name是vue实例的一个属性,可以触发响应式代理的更新.也就是会触发vue实例身上为name属性添加的get与set。
到此这篇关于浅谈vue中的data与_data的关系是什么的文章就介绍到这了,更多相关vue data与_data内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
最新评论