对Vue数据响应式的理解

466 阅读1分钟

什么是响应式?

这是一个比较模糊的概念。通常可以理解成对某些操作有所反应。比如响应式网页就是网页内容对窗口大小的变化有所反应,根据窗口大小动态改变网页内容。
Vue的数据响应式指的是数据发生变化时,UI对这种变化有所反应,即会更新UI。

Object.defineProperty()

监听

Vue实现数据响应式主要使用JS的Object.defineProperty(),该API可以设置属性的getter\setter。从而实现监听数据。

    let obj = { name: "feng" };
    let _name = obj.name;
    Object.defineProperty(obj, "name", {
        get() {
            console.log("您获取了name属性值");
            return _name;
        },
        set(value) {
            console.log("您设置了name属性值");
            _name = value;
        },
    });

image.png

使用Object.defineProperty()对name进行劫持后,之后对name属性的读写操作都是走getter或setter。那么我们就可以在getter和setter中通知UI,UI从而进行更新。

代理

Object.defineProperty()还可以实现代理功能。当我们使用data数据时,都是this.name的形式调用的。此时就产生疑问了?this指的是Vue实例,怎么就能读写我们定义的data呢?答案就是Vue代理了data。

let obj = { name: "feng" };
function proxy(data) {
//监听
let _name = data.name;
Object.defineProperty(data, "name", {
  get() {
    console.log("您获取了name属性值");
    return _name;
  },
  set(value) {
    console.log("您设置了name属性值");
    _name = value;
  },
});
//代理
const obj = {};
Object.defineProperty(obj, "name", {
  get() {
    return data.name;
  },
  set(value) {
    data.name = value;
  },
});
return obj;
}
//此处可看成const vm = new Vue(options)
let vueInstance = proxy(obj);
//此时就可以通过vue实例去访问name属性
console.log(vueInstance.name);

this.$set()和Vue.set()

通过上述内容,可以发现想要对数据进行劫持,那么数据一开始就要有属性。换句话说,对于数据后添加的属性,Vue是监听不到的。那么就无法实现数据响应式、更新UI了。因此Vue提供了两个API应对这种情况。

  • this.$set()
  • Vue.set()
    这两个API其实是一样的,都是指向同一个函数即this.$set === Vue.set表达式的值是true。
  1. 参数一:要修改的对象
  2. 参数二:修改的属性
  3. 参数三:属性值
{
    data(){
        return {
            obj:{
                name:'feng'
            }
        }
    },
    methods:{
        setAge(){
            //设置新增的属性
            this.$set(this.obj,'age',18)
        }
    }
}