实现原理
对象类型:通过Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)。
数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。
大致原理:
let person = {
name:'张三',
age:18
}
let p = {}
Object. (p,'name',{
//一些配置项
// enumerable:true,
// // enumerable:true, //控制属性是否可以枚举,默认值是false
// writable:true, //控制属性是否可以被修改,默认值是false
// configurable:true,//控制属性是否可以被删除,默认值是false
get(){
return person.name
},
set(value){
console.log('有人修改了name属性,我要去更新界面!')
person.name = value
}
})
Object.defineProperty(p,'age',{
get(){
return person.age
},
set(value){
console.log('有人修改了age属性,我要去更新界面!')
person.age = value
}
})
存在问题
新增属性或者删除属性 通过Object.defineProperty()方法 页面不会自动更新
直接通过下标修改数组,界面不会自动更新
示例
<template>
<div id="app">
<h3>姓名:{{ person.name }}</h3>
<h3>性别:{{ person.sex || "-" }}</h3>
<h3>年龄:{{ person.age }}</h3>
<el-button type="primary" size="small" @click="updateAge">更新年龄</el-button>
<el-button type="primary" size="small" @click="addSex">新增性别属性</el-button>
<el-button type="primary" size="small" @click="deleteName">删除年龄属性</el-button>
<el-button type="primary" size="small" @click="updateArray">修改爱好数组值</el-button>
</div>
</template>
<script>
export default {
name: "App",
components: {},
data() {
return {
person: {
name: "张三",
age: 18,
hobby: ['吃饭','睡觉','打游戏'],
},
};
},
mounted() {
console.log(this.person);
},
methods: {
updateAge() {
this.person.age++;
console.log(this.person.age);
},
addSex() {
this.person.sex = "男";
console.log(this.person.sex);
},
deleteName() {
delete this.person.name;
console.log(this.person.name);
},
updateArray() {
this.person.hobby[0] = '吃零食';
console.log(this.person.hobby[0]);
},
},
};
</script>
当我们点击更新年龄的时候:数据会变 页面会发生更新
当我们点击新增性别属性 删除年龄属性的时候: 数据会变页面不会发生更新
当我们点击修改爱好数组的时候 :数据会变页面不会发生更新
依次点击 结果如下
Vue2 如何解决这一问题?
新增对象属性 修改数组 我们使用 Vue.set()或 this.$set()方法
删除 我们使用 Vue.delete或 this.$delete()方法
方法修改如下
methods: {
updateAge() {
this.person.age++;
console.log(this.person.age);
},
addSex() {
// this.person.sex = "男";
this.$set(this.person,'sex','男')
console.log(this.person.sex);
},
deleteName() {
// delete this.person.name;
this.$delete(this.person,'name',)
console.log(this.person.name);
},
updateArray() {
// this.person.hobby[0] = '吃零食';
this.$set(this.person.hobby,0,'吃零食')
console.log(this.person.hobby[0]);
},
},
结果如下: