vue2.x中的响应式
实现原理:
对象类型:使用
Object.defineProperty()对对象的属性读取,修改进行拦截(数据劫持);数组类型:通过重新数组一系列方法来实现拦截(对数组变更的方法进行了包裹);
存在问题:
由于 Object.defineProperty() 对对象的属性只是进行读取和修改,所以当新增属性或者删除属性页面不会更新。同样直接通过下标更改数组页面不会更新;
解决方案:
vue 提供了 $set 和 $delete 两个实例方法,让开发者通过这两个实例方法对已有响应式对象添加或删除属性;
案例展示:
<template>
<div class="box">
<h3 class="box-title">实现响应式原理:</h3>
<div>
<span>姓名:{{ person.name }}</span>
<span>年龄:{{ person.age }}</span>
<span>性别:{{ person.sex }}</span>
<span>爱好:{{ hoppy }}</span>
</div>
<div class="box-button">
<button @click="deleteAge">删除年龄</button>
<button @click="addSex">添加性别</button>
<button @click="changeHoppy">更改爱好</button>
</div>
</div>
</template>
<script>
export default {
data () {
return {
person: {
name: '小明',
age: 18
},
hoppy: ['打球', '睡觉']
}
},
methods: {
// 点击删除年龄
deleteAge () {
// console.log(this.person.age) // 18
// delete this.person.age //数据变化,视图没有更新
// console.log(this.person.age) // undefined
// 解决办法
this.$delete(this.person, 'age')
},
// 点击添加年龄
addSex () {
// console.log(this.person.sex) // undefined
// this.person.sex = '女' //数据变化,视图没有更新
// console.log(this.person.sex) // 女
// 解决办法
this.$set(this.person, 'sex', '女')
},
// 修改爱好
changeHoppy () {
// this.hoppy[0] = '学习' // 视图没有更新
// 由于vue对splice方法进行了包裹,所以使用数组的方法可以实现视图的更新
// this.hoppy.splice(0, 1, '学习')
// 也可以使用this.$set()
this.$set(this.hoppy, 0, '学习')
}
}
}
</script>
vue3.x中的响应式
实现原理:
通过
Proxy代理拦截属性的变化,包括新增,删除,修改,查看。通过
Reflect反射对拦截的属性进行操作。
案例展示
let person = { name: "小明", age: 12 };
let p = new Proxy(person, {
//get方法用于拦截对象属性的读取,参数target是源对象,propKey是读取的属性,
get(target, propKey) {
//拦截读取属性
return Reflect.get(target, propKey);
},
set(target, propKey, value) {
//拦截对象属性或者添加新属性
Reflect.set(target, propKey, value);
},
deleteProperty(target, propKey) {
//拦截删除属性
return Reflect.deleteProperty(target, propKey);
},
});