浅谈VUE2中实现响应式的原理

VUE2.X 中 响应式原理Object.defineProperty() 的基本使用

  1. 对象类型:通过 Object.defineProperty() 对属性的读取、修改进行拦截(数据劫持)。
  2. 数组类型:通过重写更新数组的方法来实现拦截(对数组的变更方法进行了包裹)。
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、使用 Vue.set或者this.$set进行添加或修改,Vue.delete 或者 this.$delete进行删除。
2、使用 vue 实例对象上的 $nextTick 进行页面更新。
3、使用数组的一些方法对数组进行操作(如 splice() )。

区别:Vue.set 可以设置实例创建之后添加的新的属性,(在data里未声明的属性),
this.$set只能设置实例创建后存在的属性。