vue中的data与_data的关系是什么

vue中的data与_data的关系是什么 -代理

在 Vue 实例中,data 属性是用户定义的用于存储数据的对象,而 _data 是 Vue 内部用于存储数据的对象。它们之间的关系是 Vue 实例的 data 属性实际上是对 _data 的代理。

当你在创建 Vue 实例时,Vue 会将用户定义的 data 属性与内部的 _data 对象建立关联,并在代理过程中添加一些访问和观察的逻辑。这样,你在访问 Vue 实例中的数据时实际上是在访问 _data 中的数据。

下面是一个简单的示例:

html 复制代码
<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 的响应式系统,导致数据不被正确地追踪和更新。

下面是一个实例,直接修改数组中第一个元素对象的值。

javascript 复制代码
<!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会拦截数组的变异方法(例如 pushpopshiftunshiftsplicesort),从而能够在这些方法执行时触发视图更新。

然而,直接通过索引赋值的方式修改数组元素this.persons[0] = {id:'001',name:'马老师',age:50,sex:'男'},绕过了 Vue 的代理,Vue 无法检测到这样的变化,因此不会触发视图更新。

this.persons[0].name = '马老师' 这种方式可以生效的原因是因为name是vue实例的一个属性,可以触发响应式代理的更新.也就是会触发vue实例身上为name属性添加的get与set。

相关推荐
腾讯TNTWeb前端团队2 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰5 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪5 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪5 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy6 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom7 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom7 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom7 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom7 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom7 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试