这是我参与8月更文挑战的第22天,活动详情查看:8月更文挑战
前言
理解 Vue 响应式原理,我个人比较推荐的方法是结合源码来看。Vue响应式原理,你所需要知道的 首先,各位再熟悉不过的,一定是 Vue 官方提供的这张示意图了:我们以这张图为基础,先帮助大家重新捋一遍响应式的机制。在这个基础上,再去做更进一步的分析。注意我们图中有三个关键角色:Watcher、Data、和 Render。
Vue 会对传入的 data 做处理:为每一个属性添加 getter 和 setter。在这个过程中,涉及到了 Object.defineProperty 这个方法。
同时每一个 Vue 组件实例,都对应着一个 watcher 实例;这个 watcher 实例仿佛一个跟踪狂,它的目光永远跟随着 data: 由于 render 函数的执行依赖于数据的读取,因此渲染时必定会读取 data 属性进而触发其对应的 getter 方法。getter 方法被调用后,会通知到 watcher,watcher 就会把这些 getter 方法被触发的属性记录为“依赖”—— 这一过程,就是大家常常听到的“依赖收集”过程。
如果 data 发生了更新,也就是说被“写”了,此时对应属性的 setter 方法就会被触发。setter 也会去通知 watcher, 告诉它“我改变了”。watcher 拿到消息后,立刻跑去告诉 render:“data变了,你也给我跟着变!”。由此去触发一个 re-render 的过程、与数据更新相关的组件会重新渲染。
源码分析
Object.defineProperty
Object.defineProperty()
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。它的调用形式如下:
其中第一个入参,是我们操作的目标对象;第二个入参,是我们需要修改的属性的名称;第三个入参,是一个描述符,用来描述你到底要对这个目标属性做什么。
我们在 Vue 响应式原理中涉及到的“描述符”,就是 getter/setter 方法:
getter
方法: 一个给属性提供 getter 的方法,实际方法名为“get”;如果没有 getter 则为 undefined 。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传入this 对象(由于继承关系,这里的this 并不一定是定义该属性的对象)。默认为 undefined。
setter
方法: 一个给属性提供 setter 的方法,实际方法名为“set”;如果没有 setter 则为 undefined 。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。默认为 undefined。
Observer、Dep 和 Watcher 的关系
在源码层次,大家需要把握好这三个角色:
Observer
:处理 data 的家伙。它会给 data 安装 getter 和 setter,这些安装上的逻辑会联动 Dep 去完成依赖收集和更新的派发;
Dep
:实际通知 Watcher 的人。在 getter 和 setter 逻辑中,正是通过调度 Dep 来完成信息的收集、以及和Watcher 间的通信;
Watcher
:Watcher 被通知之后,就会通知 render、进而触发重渲染了。
Observer
Observer 的作用是遍历所有的属性,给它们安装上 getter/setter 方法:
这里我们看到,具体的绑定操作是在 defineReactive 里做的:
在 defineReactive 里面,每一个 getter/setter 里面都出现了 Dep 实例。正如我们前面所介绍的一样,实际收集信息和通知 watcher 的工作是 Dep 来做的。每一个属性都对应一个单独的 Dep 实例。
在 getter 方法里面,调用了 dep 的 depend 方法,这个方法有什么玄机呢?我们来看看 Dep 的结构:
Dep
Dep 的角色,宛如一个“工具人”,它是 Watcher 和 Observer 之间的纽带,是“通信兵”:
在 Dep 内部,会维护一个 watcher 队列。
depend 方法在每次 getter 触发时都会把 watcher 实例和 dep 实例做一次关联。
在 setter 触发时,dep 实例便会逐个通知每一个和自己有关联的 watcher:我对应的属性发生了更新!进而调度watcher 实例的 update 方法,实现视图更新。
Watcher
这里需要大家注意一点:宏观上看,咱们说“收集依赖”,是指 watcher 去收集自己所依赖的数据属性;不过从实现上来看,实际上是把 watcher 对象推入了 dep 实例的队列里,更像是 dep 在“收集” watcher。
其实,不管是谁来维护队列、谁“收集”谁,其本质目的都是建立起 dep 和 watcher 间的关联,达到 dep 发生变化后可以立刻通知到 watcher 的目的。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!