我们在Vue的时候一直在和数据打交道,将我们的目标数据放在data中,然后html中的插值语法{{xxx}},或者是<input type="text" v-model:value="">这种指令语法,可以响应试渲染数据,(data数据的变化直接响应式更新页面,无需操作dom),但是问题来了,我们Vue是如何监测到data中数据的改变的呢?,这里就涉及到Vue监测数据的问题了.
Vue中如何监测到data中的数据的改变的呢,即下图中model数据变化了VIewModel(vm)也是Vue实例是如何监测到的呢,下图中model-->viewmodel的线(下半截子)
mvvm模型我们都知道data中数据变化了传导到Vue实例上,Vue实例做了一系列繁重活,vue页面就被data中的数据渲染了,不需要我们操作dom,但是现在我们要探讨的是model层data中数据变化了,ViewModel是如何监测到的呢 ?
下面我们要 探讨的是vue是如何监测到data对象数据的变化的呢?----->Veu..set这个api------->再到Vue是如何监测data数组数据变化的呢,
Vue的监测name与address的改变靠的就是get与set
下面我们细细的谈一下:
首先要明白vm(vue实例)上为什么会有这两属性,不应该是写成vm._data.name和vm._data.address
这里我们简单说明一下这个数据代理
根据mvvm模型,model层的数据,传过来之后,Vue执行的 @1 第一件事就是加工一下这些数据
data --> vm._data(形式上示这样的,底层有些不一样),也可以这样说Vue收到这个数据把他放到了vm属性vm_data中,@2 第二件事由于底层代码的支持会自动给_data中每个数据,在_data的外部(即同级)添加对应新的元素(即数据代理),如上图☝🏻中的name、address,同时每个name、address中都会有setter、getter函数。
其实这样Vue强大的响应试 name改了 --》 set调用 ---一调用解析模板---》模板被解析,生成新的虚拟dom,新旧dom对比--->更新页面
Vue的监测name与address的改变靠的就是get与set
vue监测数据的原理谈完了,现在看一Vue监测对象变化时, 产生了更新时的一个问题,
先看代码:
<!--准备一个容器-->
<div id="root">
<!-- {{name}} -->
<!--遍历数组-->
<h2>人员列表(遍历数组)</h2>
<button @click="updataMei">更新马冬梅的信息</button><!--点击事件马冬梅-->
<ul>
<li v-for="(person,index) of persons" :key="person.id"> <!--遍历数组-->
<!--person.id不会破会dom结构?-->
{{person.name}}-{{person.age}}-{{person.sex}}
<!--插值语法-->
<input type="text">
<!--html语法-->
</li>
</ul>
{{name}}
</div>
const vm =new Vue({
el: '#root',
data: {
name: "小猪佩奇佩奇身上纹",
persons: [
{ id: '001', name: "马冬梅", age: 28, sex: "女" },
{ id: '002', name: '周冬雨', age: 19, sex: "女" },
{ id: "003", name: "周杰伦", age: 30, sex: "男" },
{ id: '004', name: "郭艾伦", age: 21, sex: "男" }
]
},
methods: {
updataMei() {
// this.persons[0].name="马什么梅",//奏效
// this.persons[0].age=50, //奏效
// this.persons[0].sex="男" //奏效
this.persons[0] = { id: '001', name: "马什么梅", age: 3, sex: "女" }
}
},
})
点击更改马冬梅的信息之后,页面并没有任何的反应,而我们又通过方法改变了data中的数据,也就是说,这条橙色的线没有实现,data中的数据变了,Vue没有监测到
- Vue监测数据的原理大总结
- 1.Vue会监测data里的所有层次的数据
- 2.如何监测对象中的数据?
- (1) 通过setter实现监测,且要在new Vue时就传入 监测的数据
- (2)如果需要后添加的属性作为响应试,请使用api:
- Vue.set(target.propertyName/index.value)或者
- vm.$set(target.propertyName/index.value)
- 3.如何监测数组中的数据
- 通过包裹('包装')数组更新元素的方法实现',本质就是做了两件事)
- Vue对数组的监测是对数组原型对象方法包装
- (1). 调用原生对应的方法对数组进行更新
- (2).重新解析模板,进而更新页面
- 4.在Vue修改数组中的某个元素一定要用如下方法:
- 1.使用这些api: push() pop() shift() unshift() splice() sort() reverse()
-
- 2.vue,set() 或者vm.$set
-
- ps:
- Vue.set()和vm.$set()都不能给vm或者vm的根数据对象添加属性!!!