0
点赞
收藏
分享

微信扫一扫

vue2数据响应式原理——数据劫持(初始篇)


vue2数据响应式原理——数据劫持(初始篇)_响应式

vue2数据响应式原理之数据劫持(初始篇)

  • ​​前言​​
  • ​​数据劫持(初始篇)​​
  • ​​Object.defineProperty()​​

前言

写这系列博客之前,还是想感慨一下尤大大的精明厉害之处。

​vue​​​的发展大家有目共睹,这一切离不开​​vue​​​数据响应式的发明,尽管​​vue2​​​的数据响应式处理还有一些问题,但这些问题都在​​vue3​​​中进行了解决,那我为什么还要写​​vue2​​​的数据响应式原理,而不直接写​​vue3​​的数据响应式原理呢?

因为​​vue2​​​在​​vue​​的发展中是个里程碑的存在,它的一些原理和思想对之后的​​vue​​​发展奠定了基础,不管之后​​vue​​​怎么变化,这些原理也不会变,这就是本篇博文中书写​​vue2​​数据响应式原理的原因。

开始之前先附上尤大大的总结:在getter中收集依赖,在setter中触发依赖。

开始研究前先创建​​index.html​​​和​​index.js​​​两个文件,在​​index.html​​​文件中引入​​index.js​​​文件,之后我们将在​​index.js​​​文件中书写代码,运行​​index.html​​文件查看效果。

本文完整代码仓库地址: ​​Vue2 Responsive principle​​(建议初学者跟着代码来学)

一个完整的响应式应该包括:

  • 数据劫持
  • 收集依赖
  • 发布订阅

本系列查阅顺序:

  1. vue2数据响应式原理——数据劫持(初始篇)
  2. vue2数据响应式原理——数据劫持(对象篇)
  3. vue2数据响应式原理——数据劫持(数组篇)
  4. vue2数据响应式原理——依赖收集和发布订阅

数据劫持(初始篇)

为什么需要数据劫持?​​vue​​​中当我们对一个响应式数据进行更改时我们需要监听到这个响应式数据的变化,这就需要用到​​Object.defineProperty()​​​或者​​ES6​​​的​​Proxy​​​来对数据的更改操作进行劫持,之后进行一些操作后将数据更改的结果反馈给用户,这就实现了简单的响应式数据,​​vue2​​​使用的是​​Object.defineProperty()​​​所以我们这里只讲​​Object.defineProperty()​​。

Object.defineProperty()

​Object.defineProperty()​​ 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

语法:

Object.defineProperty(obj, prop, descriptor)

参数:

  • ​obj​​ 要定义属性的对象。
  • ​prop​​ 要定义或修改的属性的名称或 Symbol 。
  • ​descriptor​​ 要定义或修改的属性描述符。

先看一个小实例:

let obj = {};
Object.defineProperty(obj, "a", {
value: 3,
});
Object.defineProperty(obj, "b", {
value: "我是obj的b",
});
console.log(obj.a);
console.log(obj.b);

打印结果:

vue2数据响应式原理——数据劫持(初始篇)_vue.js_02


这里我们定义了一个​​obj​​​的空对象,然后利用​​Object.defineProperty()​​​向​​obj​​​中添加了​​a、b​​​两个属性,之后我们在访问​​obj.a​​​和​​obj.b​​时就能打印出结果。

因为​​obj​​​本身是个空对象,所以这里​​Object.defineProperty()​​​通过在​​obj​​​对象上定义​​a、b​​新属性时就实现了数据劫持,将我们处理的​​a、b​​反馈给了用户。

看到这里大家应该已经明白​​Object.defineProperty()​​的基本作用以及数据劫持的原理了。

但是这个时候大家可能会有一个问题,为什么要用​​Object.defineProperty()​​​对​​obj​​​新增属性而不直接在定义​​obj​​时定义好属性呢?

因为在使用​​Object.defineProperty()​​时我们可以对新增的属性添加一些特别的功能:

​configurable​

  • 当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。该属性详解 默认为 false。

​enumerable​

  • 当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。
    默认为 false。
    数据描述符还具有以下可选键值:

​value​

  • 该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。
    默认为 undefined。

​writable​

  • 当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符 (en-US)改变。
    默认为 false。
    存取描述符还具有以下可选键值:

​get​

  • 属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。
    默认为 undefined。

​set​

  • 属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。
    默认为 undefined。

例如:上面那个代码的例子我们试着修改a属性:

let obj = {};
Object.defineProperty(obj, "a", {
value: 3,

});
console.log(obj.a);
obj.a = 9;
console.log(obj.a);

vue2数据响应式原理——数据劫持(初始篇)_javascript_03


可以看到a并没有被修改,这就是因为​​writable​​​配置默认为false,我们修改一下​​writable​​配置:

let obj = {};
Object.defineProperty(obj, "a", {
value: 3,
//是否可写:是否可更改
writable: true,
});
console.log(obj.a);
obj.a = 9;
console.log(obj.a);

vue2数据响应式原理——数据劫持(初始篇)_javascript_04


可以看到a可以被修改了,这就是使用​​Object.defineProperty()​​​来定义​​obj​​对象属性的原因:为了能够对新增的这个属性进行一些配置。

了解了基础的​​Object.defineProperty()​​​,现在让我们来看看对象的数据劫持吧:vue2数据响应式原理之数据劫持(对象篇)


举报

相关推荐

0 条评论