> 文章列表 > Vue监测数据改变的原理

Vue监测数据改变的原理

Vue监测数据改变的原理

Vue监视数据的原理:

1.vue会监视data中所有层次的数据

2.如何监测对象中的数据?(通过setter实现监视,且要在new Vue时就传入要监测的数据)

  • 对象中后追加的属性,Vue默认不做响应式处理
  • 如需给后添加的属性做响应式,请使用如下API:
  • Vue.set(target,propertyName/index,value)
  • vm.$set(target,propertyName/index,value)

3.如何监测数组中的数据?(通过包裹数组更新元素的方法实现,本质就是做了两件事:)

  • 调用原生对应的方法对数组进行更新
  • 重新解析模板,进而更新页面

4.在Vue修改数组中的某个元素一定要用如下方法:

  • 使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
  • Vue.set() 或 vm.$set()

特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象(data等) 添加属性

先引出一个问题,可以更新人员信息的代码示例:(奏效)
点击按钮更新人员信息

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="../js/vue.js"></script>
</head>
<body>
<div id="app"><h2>人员列表</h2><button @click="updatedMei">更新马冬梅的信息</button><ul><li v-for="(p,index) in persons" :key="p.id">{{p.name}} - {{p.age}} - {{p.sex}}</li></ul>
</div>
<script>Vue.config.productionTip = falseconst vm = new Vue({el: "#app",data: {persons: [{id: '001', name: '马冬梅', age: 19, sex: '女'},{id: '002', name: '周冬雨', age: 20, sex: '女'},{id: '003', name: '周杰伦', age: 21, sex: '男'},{id: '004', name: '温兆伦', age: 22, sex: '男'}]},methods: {updatedMei() {this.persons[0].name = '马老师'this.persons[0].age = 50this.persons[0].sex = '男'}}})
</script>
</body>
</html>

点击按钮更新不了的代码示例:(不奏效)

这个实实在在的是把数据改了,只不过,vue没有监测到

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="../js/vue.js"></script>
</head>
<body>
<div id="app"><h2>人员列表</h2><button @click="updatedMei">更新马冬梅的信息</button><ul><li v-for="(p,index) in persons" :key="p.id">{{p.name}} - {{p.age}} - {{p.sex}}</li></ul>
</div>
<script>Vue.config.productionTip = falseconst vm = new Vue({el: "#app",data: {persons: [{id: '001', name: '马冬梅', age: 19, sex: '女'},{id: '002', name: '周冬雨', age: 20, sex: '女'},{id: '003', name: '周杰伦', age: 21, sex: '男'},{id: '004', name: '温兆伦', age: 22, sex: '男'}]},methods: {updatedMei() {this.persons[0] =  {id: '001', name: '马老师', age: 50, sex: '男'}}}})
</script>
</body>
</html>

打开控制台看一下:

现在模拟一个数据监测:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<script>let data = {name: '尚硅谷',address: '北京'}//创建一个监视的实例对象,用于监视data中属性的变化const obs = new Observer(data)console.log(obs)//准备一个vm实例对象let vm = {}vm._data = data = obsfunction Observer(obj) {//汇总对象中所有的属性形成一个数组const keys = Object.keys(obj)keys.forEach((k) => {//this指代Observer这个对象Object.defineProperty(this, k, {get() {return obj[k]},set(val) {console.log('${k}被改了,我要去解析模板,生成虚拟DOM,...我要开始忙了!')obj[k] = val}})})}
</script>
</body>
</html>

Vue数据监视:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>button {margin-top: 10px;}</style><script src="../js/vue.js"></script>
</head>
<body>
<div id="app"><h1>学生信息</h1><button @click="student.age++">年龄+1岁</button><br><button @click="addSex">添加性别属性,默认值男</button><br><button @click="addFriend">在列表首位添加一个朋友</button><br><button @click="updateFirstFriendName">修改第一个朋友的名字为:张三</button><br><button @click="addHobby">添加一个爱好</button><br><button @click="updateHobby">修改第一个爱好为:开车</button><br><button @click="removeSmoke">过滤掉爱好中的抽烟</button><br><h3>姓名:{{student.name}}</h3><h3>年龄:{{student.age}}</h3><h3 v-if="student.sex">性别:{{student.sex}}</h3><h3>爱好</h3><ul><li v-for="(h,index) in student.hobby" :key="index">{{h}}</li></ul><h3>朋友们</h3><ul><li v-for="(f,index) in student.friends" :key="index">{{f.name}} -- {{f.age}}</li></ul>
</div>
<script>Vue.config.productionTip = falseconst vm = new Vue({el: "#app",data: {student: {name: 'tom',age: 18,hobby: ['抽烟', '喝酒', '烫头'],friends: [{name: 'jerry', age: 35},{name: 'tony', age: 36}]}},methods: {addSex() {// Vue.set(this.student,'sex','男')this.$set(this.student, 'sex', '男')},addFriend() {this.student.friends.unshift({name: 'jack', age: 70})},updateFirstFriendName() {this.student.friends[0].name = '张三'},addHobby() {this.student.hobby.push('学习')},updateHobby() {this.student.hobby.splice(0, 1, '开车')},removeSmoke() {this.student.hobby = this.student.hobby.filter((h) => {return h !== '抽烟'})}}})
</script>
</body>
</html>

优途网