vue监测数据的原理、vue.set的使用
我们更新列表中的某条数据,采用不同的方式更新,会出现不同的情况,如下面代码
<div id="app"><button @click="updateInfo">更新张三数据</button><ul><li v-for="p in persons" ::key="p.id">{{p.name}}--{{p.age}}--{{p.sex}}</li></ul></div><script>Vue.config.productionTip = false;new Vue({el: "#app",data: {persons: [{id: 1,name: "张三",age: 21,sex: "男",},{id: 2,name: "李四",age: 18,sex: "男",},],},methods: {updateInfo() {/*此种方式生效this.persons[0].name = "王五";this.persons[0].age = 22;this.persons[0].sex = "女";*/this.persons.splice(0,1,{id:1,name:"王五",age:22,sex:"女"})// 但这种不生效this.persons[0] = { id: 1, name: "王五", age: 22, sex: "女" };},},});</script>
为什么使用this.persons[0] = { id: 1, name: "王五", age: 22, sex: "女" };不生效
一、Vue是如何监测对象变化的
我们所传入的data,vue拿到之后进行加工,加工之后执行vm_data = data。为什么要进行加工?加工之后就可以实现响应式。当name修改之后,会执行调用setter,setter中的函数会使页面重新解析模板,模板重新解析生成新的虚拟DOM,然后进行新旧DOM对比,然后更新页面。
二、Vue监视数据的原理
1、vue会监视data中所有层次的数据。
2、如何监视对象中的数据?
通过setter实现监视,且要在new Vue时就传入要监测的数据。(简单说就是data中默认就声明了这些数据)
如果之前未声明,通过在对象中后追加的属性,Vue默认不做响应式处理。因为追加的属性没有getter和setter,比如:
<div id="app"><p>姓名:{{student.name}}</p><p>性别:{{student.sex}}</p><p v-if="student.age">年龄:{{student.age}}</p><button @click="addAge">添加年龄</button></div><script>const vm = new Vue({el:"#app",data:{student:{name:"张三",sex:"男"}},methods:{addAge(){this.student.age = 18;// 这种方式不生效}}})</script>
上述代码我们执行之后查看数据发现,通过此方法追加的属性没有getter和setter
如果需要给后添加的属性做响应式,请使用如下API:
Vue.set(target,propertyName/index,value)或vm.$set(target,protertyName/index,value)
<div id="app"><p>姓名:{{student.name}}</p><p>性别:{{student.sex}}</p><p v-if="student.age">年龄:{{student.age}}</p><button @click="addAge">添加年龄</button></div><script>const vm = new Vue({el:"#app",data:{student:{name:"张三",sex:"男"}},methods:{addAge(){this.$set(this.student,"age",18)}}})</script>
上述代码我们执行之后查看数据发现,通过此方法新增的属性会被添加上getter和setter
3、如何监测数组中的数据?
通过包裹数组更新元素的方法实现,本质就是做了两件事:
调用原生对应的方法对数组进行更新。
重新解析模板,进而更新页面
在Vue修改数组中的某个元素一定要用如下方法:
使用这些API:push()、pop()、shift()、unshift()、spice()、sort()、reverse()
<div id="app"><ul><p>爱好:</p><button @click="addHobby">增加一个爱好</button><li v-for="(h,index) in hobby" :key="index">{{h}}</li></ul></div><script>Vue.config.productionTip = false;var vm = new Vue({el: "#app",data: {hobby: ["篮球", "羽毛球", "跑步"],},methods: {addHobby() {this.hobby.push("跳舞");},},});</script>Vue.set()或vm.$set()
<div id="app"><ul><p>爱好:</p><button @click="addHobby">增加一个爱好</button><li v-for="(h,index) in hobby" :key="index">{{h}}</li></ul></div><script>Vue.config.productionTip = false;var vm = new Vue({el: "#app",data: {hobby: ["篮球", "羽毛球", "跑步"],},methods: {addHobby() {this.$set(this.hobby, 3, "跳舞");},},});</script>
特别注意:Vue.set()和vm.$set()不能给vm或vm的根数据对象添加属性
