VUE2.X 中 响应式原理Object.defineProperty() 的基本使用
- 对象类型:通过
Object.defineProperty() 对属性的读取、修改进行拦截(数据劫持)。 - 数组类型:通过重写更新数组的方法来实现拦截(对数组的变更方法进行了包裹)。
Object.defineProperty("对象", "属性", { value: 0, // 属性值 enumerable: true, // 属性是否可被枚举,默认 false writable: true, // 属性是否可被修改,默认 false configurable: true, // 属性是否可被删除,默认 false get() {}, // 获取属性值时调用,此函数需返回属性的属性值 set(value) {}, // 修改属性值时调用,value为修改后的值 })
1.简单例子
var example = {}; //定义属性 Object.defineProperty(example, "name", { value: "tom", }); console.log(example);
2.使用defineProperty重新定义属性name,访问时更新界面
.初始定义时
var example = {}; var name = "Tom"; //定义属性 Object.defineProperty(example, "name", { get() { console.log("读取属性时调用的方法:get-"+name); return name; }, //写入属性调用的方法set set(value) { console.log("赋值前-"+name); name = value; console.log("赋值后-"+name); }, }); console.log(example.name);
可以看到此时set方法并没有被执行,console的时候只用到了get方法读取属性name
.后续修改定义参数时
var example = {}; var name = "Tom"; //定义属性 Object.defineProperty(example, "name", { get() { console.log("读取属性时调用的方法:get-"+name); return name; }, set(value) { console.log("赋值前-"+name); name = value; console.log("赋值后-"+name); }, }); example.name = "mark"; console.log(example.name);
按照上一个例子,此时先执行了赋值 example.name = "mark"; 那么会优先通过set方法赋值,然后console的时候读取该属性
VUE2存在的问题
1、新增属性、删除属性,界面不会更新。
2、直接通过下标修改数组,界面不会自动更新。
但是VUE2提供了一些方法解决上述问题:
1、使用
2、使用 vue 实例对象上的
3、使用数组的一些方法对数组进行操作(如 splice() )。
区别:
Vue.set 可以设置实例创建之后添加的新的属性,(在data里未声明的属性),
this.$set 只能设置实例创建后存在的属性。