vue2.x
- 对象类型:通过object.defineProperty()对属性的读取、修改进行拦截(数据劫持)
- 数组类型:通过重写更新数组的一系列方法实现拦截。(对数组的变更方法进行包裹)
存在的问题:(能解决,不太方便) - 新增属性、删除属性,页面不会更新。
- 直接通过下标修改数组,界面不会自动更新。
写一个简单的例子
<template>
<div>
<p>姓名:{{ person.name }}</p>
<p>年龄:{{ person.age }}</p>
<p>朋友:{{ person.friend ? person.friend : "没有朋友" }}</p>
<button @click="add">新增朋友</button>
<button @click="del">删除朋友</button>
</div>
</template>
<script>
export default {
data() {
return {
person: {
name: "张三",
age: 18,
},
};
},
methods: {
add() {
this.person.friend = "李四";
console.log("this.person", this.person);
},
del() {},
},
};
</script>
<style scoped>
</style>
通过打印可以发现,数据变化,但是页面没有更新。这是因为friend只是一个普通的数据,便不是被object.defineProperty代理的数据。
想处理这种情况,可以用vue一个api $set实现。
<template>
<div>
<p>姓名:{{ person.name }}</p>
<p>年龄:{{ person.age }}</p>
<p>朋友:{{ person.friend ? person.friend : "没有朋友" }}</p>
<button @click="add">新增朋友</button>
<button @click="del">删除朋友</button>
</div>
</template>
<script>
export default {
data() {
return {
person: {
name: "张三",
age: 18,
},
};
},
methods: {
add() {
// this.person.friend = "李四";
// console.log("this.person", this.person);
this.$set(this.person, "friend", "李四");
},
del() {},
},
};
</script>
<style scoped>
</style>
或者调用vue.set也是可以实现的
<template>
<div>
<p>姓名:{{ person.name }}</p>
<p>年龄:{{ person.age }}</p>
<p>朋友:{{ person.friend ? person.friend : "没有朋友" }}</p>
<button @click="add">新增朋友</button>
<button @click="del">删除朋友</button>
</div>
</template>
<script>
import vue from "vue";
export default {
data() {
return {
person: {
name: "张三",
age: 18,
},
};
},
methods: {
add() {
// this.person.friend = "李四";
// console.log("this.person", this.person);
vue.set(this.person, "friend", "李四");
console.log("person", this.person);
},
del() {},
},
};
</script>
<style scoped>
</style>
完善一下删除的逻辑和打印的结果
<template>
<div>
<p>姓名:{{ person.name }}</p>
<p>年龄:{{ person.age }}</p>
<p>朋友:{{ person.friend ? person.friend : "没有朋友" }}</p>
<button @click="add">新增朋友</button>
<button @click="del">删除朋友</button>
</div>
</template>
<script>
// import vue from "vue";
export default {
data() {
return {
person: {
name: "张三",
age: 18,
},
};
},
methods: {
add() {
// this.person.friend = "李四";
this.$set(this.person, "friend", "李四");
},
del() {
delete this.person.name;
console.log("del person", this.person);
},
},
};
</script>
<style scoped>
</style>
发现数据更新了,页面没有发生变化。
defineProperty上只有两个属性,get和set,对于删除操作而言,是defineProperty解决不了的。但是可以通过this.$delete移除一个响应式数据。
<template>
<div>
<p>姓名:{{ person.name }}</p>
<p>年龄:{{ person.age }}</p>
<p>朋友:{{ person.friend ? person.friend : "没有朋友" }}</p>
<button @click="add">新增朋友</button>
<button @click="del">删除姓名</button>
</div>
</template>
<script>
// import vue from "vue";
export default {
data() {
return {
person: {
name: "张三",
age: 18,
},
};
},
methods: {
add() {
// this.person.friend = "李四";
this.$set(this.person, "friend", "李四");
},
del() {
// delete this.person.name;
this.$delete(this.person, "name");
console.log("del person", this.person);
},
},
};
</script>
<style scoped>
</style>
打印结果如下(调用vue实例的话,就是vue.delete)
对于第二个问题,直接通过下标修改数组,界面不会自动更新,继续上一个代码片段及打印结果。
<template>
<div>
<p>姓名:{{ person.name }}</p>
<p>年龄:{{ person.age }}</p>
<p>朋友:{{ person.friend ? person.friend : "没有朋友" }}</p>
<p>爱好:{{ person.hobby }}</p>
<button @click="add">新增朋友</button>
<button @click="del">删除姓名</button>
<button @click="edit">修改爱好</button>
</div>
</template>
<script>
// import vue from "vue";
export default {
data() {
return {
person: {
name: "张三",
age: 18,
hobby: ["吃饭", "睡觉", "打豆豆"],
},
};
},
methods: {
add() {
// this.person.friend = "李四";
this.$set(this.person, "friend", "李四");
},
del() {
// delete this.person.name;
this.$delete(this.person, "name");
console.log("del person", this.person);
},
edit() {
this.person.hobby[0] = "学习";
},
},
};
</script>
<style scoped>
</style>
数据发生变化,页面没有更新,实现更新也是通过this.$set或者vue.set,还有数组方法splice(this.person.hobby,splice(0,1,'学习’),打印结果如下
<template>
<div>
<p>姓名:{{ person.name }}</p>
<p>年龄:{{ person.age }}</p>
<p>朋友:{{ person.friend ? person.friend : "没有朋友" }}</p>
<p>爱好:{{ person.hobby }}</p>
<button @click="add">新增朋友</button>
<button @click="del">删除姓名</button>
<button @click="edit">修改爱好</button>
</div>
</template>
<script>
// import vue from "vue";
export default {
data() {
return {
person: {
name: "张三",
age: 18,
hobby: ["吃饭", "睡觉", "打豆豆"],
},
};
},
methods: {
add() {
// this.person.friend = "李四";
this.$set(this.person, "friend", "李四");
},
del() {
// delete this.person.name;
this.$delete(this.person, "name");
},
edit() {
// this.person.hobby[0] = "学习";
this.$set(this.person.hobby, 0, "学习");
console.log("person", this.person);
},
},
};
</script>
<style scoped>
</style>