一、回顾Vue2的响应式
-
实现原理:
-
对象类型:通过
Object.defineProperty()
对属性的读取、修改进行拦截(数据劫持)。 -
数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。
Object.defineProperty(data, 'count', { get () {}, set () {} })
-
-
存在问题:
- 新增属性、删除属性, 界面不会更新。
- 直接通过下标修改数组, 界面不会自动更新。
以下方式对在data函数中没有定义的对象属性,直接增删是没有响应式的
<script>
let person = { name: "张三", age: "18" };
let p = {};
Object.defineProperty(p, "name", {
configurable: true,
get() {
console.log("有人读取了p的name属性");
return person.name;
},
set(newVal) {
console.log("有人修改了p的name属性,我要去更新页面了");
person.name = newVal;
},
});
Object.defineProperty(p, "age", {
configurable: true,
get() {
console.log("有人读取了p的age属性");
return person.age;
},
set(newVal) {
console.log("有人修改了p的age属性,我要去更新页面了");
person.age = newVal;
},
});
</script>
<template>
<div id="app">
<h1>姓名:{{ person.name }}</h1>
<h1 v-show="person.sex">性别:{{ person.sex }}</h1>
<h1>爱好:{{ hobboy.toString() }}</h1>
<button @click="addSex">添加一个sex属性</button>
<button @click="delSex">删除sex属性</button>
<button @click="editHobby">修改第一个爱好</button>
</div>
</template>
<script>
import Vue from "vue";
export default {
data() {
return {
person: {
name: "张三",
},
hobboy: ["抽烟", "喝酒", "烫头"],
};
},
methods: {
addSex() {
// 无效(没有响应式)
// this.person.sex = "男";
// 解决方式一
// this.$set(this.person, "sex", "女");
// 解决方式二
// Vue.set(this.person, "sex", "女");
// 解决方式三
// this.person.sex = "男";
// this.$forceUpdate();
},
delSex() {
// 无效(没有响应式)
// delete this.person.sex;
// 解决方式一
// this.$delete(this.person, "sex");
// // 解决方式二
// Vue.delete(this.person, "sex");
// 解决方式三
// delete this.person.sex = "男";
// this.$forceUpdate();
},
editHobby() {
// 无效(没有响应式)
// this.hobboy[0] = "学习";
// 方式一
// this.$set(this.hobboy, 0, "学习");
// 方式二
// this.hobboy.splice(0, 1, "学习");
// 解决方式三
// this.hobboy = ["学习","喝酒", "烫头"];
// 解决方式四
// this.hobboy[0] = "学习";
// this.$forceUpdate();
},
},
};
</script>
网友评论