【手把手教你搓Vue响应式原理】(一)初识Vue响应式

1,091 阅读3分钟

大家好,我是 辉夜真是太可爱啦 。这是我最近在写的【手把手教你搓Vue响应式原理】系列,本文将一步步地为你解开vue响应式原理的面纱。由于本人也是在写这篇文章的过程中不断试错,不断学习改进的,所以,本文同样很适合和我一样的初学者。和 Vue 的设计理念如出一辙,那就是渐进增强

MVVM

在讲这个之前,首先要明白一点,这个所谓的响应式,其实本身就是对 MVVM 的理解。

MVVM 其实就是所谓的 Modal View ViewModal

简单理解,就是你的 data 中的数据,和 template 模板中的界面,本身就是两个东西。

但是, Vue 给你做了一层中间的 ViewModal,让视图上的改变能反映到 data 中, data 中的改变能反映到视图上。

image.png

在这个反映过程中,ViewModal就是视图和数据的一个桥梁。

非侵入式和侵入式

同样是让 a + 1

Vue 中,这个桥梁是你看不见的,因为 Vue 都帮你完成了视图和数据的变化传递。

React 就是侵入式的,因为要显式地声明 setState ,通过它,来设置变量的同时,设置视图的改变。

image.png

所以,所谓的侵入式,其实就是对于桥梁的侵入。

Vue的神奇之处

所以, Vue 的神奇之处就在于,不需要我们手动地显示调用 setState ,也就是这个桥梁, Vue 已经帮我们桥接上了。

要让 data 改变的同时,视图也发生改变,所以,问题的所在,就是我们需要监听,什么时候,这个变量发生了变量。

然而, ES5 中,就有那么一个特性,可以做到对于数据的劫持(监听)。

它就是 Object.defineProperty

Object.defineProperty

Object.defineProperty( obj, prop, descriptor ) 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象,与此同时,它可以对对象的一些额外底层的属性进行设置。例如可以设置writableenumerable , configurable 等属性。

后面的额外属性设置,才是我们使用它的重点。

但是,我们使用的不是上面的几个属性,最主要的还是它的 get set ,可以对属性值的获取和设置操作进行拦截。

  • get

get主要是可以对值的获取进行拦截,,它必须要传入一个 return ,并且,该函数的返回值会被用作属性的值。我们可以来看一个例子:

image.png

let a={name:'jack'};
Object.defineProperty(a,'name',{
  get(){
    return '你已经被拦截了!';
  },
})
console.log(a.name);    //你已经被拦截了!

由于设置了 get ,所以,输出 a.name 的时候直接会被拦截,走 get() 中的 return 所以,此时,a.name 的值应该是 你已经被拦截了!。

  • set

set主要是可以对值的设置进行拦截,该方法会接受一个参数,那就是被赋予的新值。我们可以来看一个例子:

let a={name:'jack'};
Object.defineProperty(a,'name',{
  set(newValue){
    console.log('你正在设置值' + newValue);
  }
})
a.name='bob';   // 你正在设置值bob

由于设置了 set ,所以,设置值的时候会被拦截,走 set() 中的方法。

文末总结

所以, Vue 能自动获取data中的改变,反映到视图的原因,就是有对于变量的获取和设置的劫持,当变量发生改变的同时, Vue 能在第一时间知道,并且对视图做出相应的改变操作。

而这把钥匙就是 Object.defineProperty

下文引荐

【手把手教你搓Vue响应式原理】(二)深度监测对象全部属性

【手把手教你搓Vue响应式原理】(三)observe 以及 ob

【手把手教你搓Vue响应式原理】(四) 数组的响应式处理

【手把手教你搓Vue响应式原理】(五) Watcher 与 Dep

文章参考

【尚硅谷】Vue源码解析之数据响应式原理

Object.defineProperty() - MDN