「面试必看」Vue百题斩~ Vue数据响应式原理的四个核心模块

vue 响应式原理的四个核心模块

Observe

Observe 要实现的目标非常简单,就是把一个普通对象转换成响应式对象。

为了实现这一点,Observe 把对象的每个属性通过 Object.defineProperty 转换为带有 settergetter 的属性,这样一来,vue就有机会在设置和访问属性的时候做点别的事情。
在这里插入图片描述

Observe 是Vue内部的构造器,我们可以通过Vue提供的静态方法Vue.observe(object)间接的使用该功能。

在组件的生命周期中,这件事发生在beforeCreate之后,create之前。
具体的实现上,它会递归遍历对象中的所有属性,以完成深度的属性转换

由于遍历时只能遍历到对象的当前属性,无法检测到将来对象动态增加或删除属性的属性,因此Vue提供了$set$delete实例方法,让开发者通过这两个实例方法对已有响应式对象添加或删除属性。

对于数组,Vue会更改它的隐式原型,目的是因为Vue需要监听那些可能改变数组内容的方法。

在这里插入图片描述

总之,Observe的目的,就是要让一个对象。它属性的读取、赋值,内部数组的变化都要能够被Vue监听到。

Dep

这里有两个问题,就是读取属性的时候做什么事,属性变化的时候要做什么事,这个问题需要依靠Dep来解决。
Dep的意思是dependency,表示依赖的意思。

Vue会为响应式对象中的每个属性、对象本身、数组本身创建一个Dep实例,每个Dep实例都有能力做以下两件事情:

  • 记录依赖:是谁要用我
  • 派发更新:我改变了,我要通知那些用到我的人

当读取响应式对象的某个属性时,它会进行依赖收集:有人用到我了;当改变某个属性时,它会派发更新:那些用到我的人听好了,我变了,要更新。

在这里插入图片描述

Watcher

这里又出现一个问题,就是Dep如何知道谁在用我?

要解决这个问题,需要依靠另外一个东西,就是Watcher
当某个函数执行的时候,用到了响应式数据,响应式数据是无法知道是哪个函数在用自己的,因此,Vue通过一个巧妙的方法来解决这个问题。

我们不要直接执行函数,而是把函数交给一个Watcher对象去执行,Watcher是一个对象,每个这样的函数执行时都应该创建一个Watcher对象,通过Watcher去执行。

watcher会设置一个全局变量,让全局变量记录当前负责执行的watcher等于自己,然后再去执行函数,当函数执行时,使用到了响应式的数据,发生了依赖记录dep.depend(),那么dep就把这个全局变量记录下来,表示有一个watcher用到了我的属性。
Dep进行派发时,它会通知之前记录的所有watcher,我变化了!

在这里插入图片描述

每一个Vue组件都至少对应一个watcher,该watcher记录了该组件的render函数。
watcher首先会把render函数执行一遍收集依赖,于是那些在render中使用到的响应式数据就会记录这个watcher
当数据变化时,dep就会通知该watcher,而watcher将重新运行render函数,从而让界面重新渲染同时重新记录当前的依赖。

Scheduler

现在还剩下随后一个问题,就是Dep通知watcher执行运行对应的函数,就有可能造成函数频繁运行,从而导致效率低下。

例如,如果一个交给watcher的函数,里面用到了a,b,c,d,那么a,b,c,d四个属性都会记录依赖,于是下面的代码将触发四次watcher,更新四次:

this.a = 'new a';
this.b = 'new b';
this.c = 'new c';
this.d = 'new d';

这样显然是不合适的,因此,watcher收到派发更新的通知后,不是立即执行函数的,而是把自己交给一个叫调度器的东西。

调度器维护一个执行队列,该队列同一个watcher只会存在一次,他会同个一个nextTick的工具方法,把这些需要执行的watcher放入到事件循环的微队列中,nextTick的具体做法是通过promise完成的。

nextTick通过this.$nextTick暴露给开发者;

也就是说,当响应式数据变化时,render函数的执行是异步的,并且在微队列中。

总体流程

在这里插入图片描述

上一篇: 「面试必看」JS百题斩~ 终于明白了原型 与 原型链

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值