详细分析vue响应式原理

2020-06-22 12:59 来源:易采站长站 作者:刘景俊 点击: 评论:

A-A+

原标题:详细分析vue响应式原理

前言

响应式原理作为 Vue 的核心,使用数据劫持实现数据驱动视图。在面试中是经常考查的知识点,也是面试加分项。

本文将会循序渐进的解析响应式原理的工作流程,主要以下面结构进行:

分析主要成员,了解它们有助于理解流程 将流程拆分,理解其中的作用 结合以上的点,理解整体流程

文章稍长,但大部分是代码实现,还请耐心观看。为了方便理解原理,文中的代码会进行简化,如果可以请对照源码学习。

主要成员

响应式原理中,Observe、Watcher、Dep这三个类是构成完整原理的主要成员。

Observe,响应式原理的入口,根据数据类型处理观测逻辑 Watcher,用于执行更新渲染,组件会拥有一个渲染Watcher,我们常说的收集依赖,就是收集 Watcher Dep,依赖收集器,属性都会有一个Dep,方便发生变化时能够找到对应的依赖触发更新

下面来看看这些类的实现,包含哪些主要属性和方法。

Observe:我会对数据进行观测

温馨提示:代码里的序号对应代码块下面序号的讲解

// 源码位置:/src/core/observer/index.js
class Observe {
 constructor(data) {
  this.dep = new Dep()
  // 1
  def(data, '__ob__', this)
  if (Array.isArray(data)) {
   // 2
   protoAugment(data, arrayMethods)
   // 3
   this.observeArray(data)
  } else {
   // 4
   this.walk(data)
  }
 }
 walk(data) {
  Object.keys(data).forEach(key => {
   defineReactive(data, key, data[key])
  })
 }
 observeArray(data) {
  data.forEach(item => {
   observe(item)
  })
 }
}
为观测的属性添加 __ob__ 属性,它的值等于 this,即当前 Observe 的实例 为数组添加重写的数组方法,比如:push、unshift、splice 等方法,重写目的是在调用这些方法时,进行更新渲染 观测数组内的数据,observe 内部会调用 new Observe,形成递归观测 观测对象数据,defineReactive 为数据定义 get 和 set ,即数据劫持

Dep:我会为数据收集依赖

// 源码位置:/src/core/observer/dep.js
let id = 0
class Dep{
 constructor() {
  this.id = ++id // dep 唯一标识
  this.subs = [] // 存储 Watcher
 }
 // 1
 depend() {
  Dep.target.addDep(this)
 }
 // 2
 addSub(watcher) {
  this.subs.push(watcher)
 }
 // 3
 notify() {
  this.subs.forEach(watcher => watcher.update())
 }
}

// 4
Dep.target = null

export function pushTarget(watcher) {
 Dep.target = watcher
} 

export function popTarget(){
 Dep.target = null
}

export default Dep
据收集依赖的主要方法,Dep.target 是一个 watcher 实例 添加 watcher 到数组中,也就是添加依赖 属性在变化时会调用 notify 方法,通知每一个依赖进行更新 Dep.target 用来记录 watcher 实例,是全局唯一的,主要作用是为了在收集依赖的过程中找到相应的 watcher

【易采站长站编辑:秋军】