Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第 39 题:vue响应式原理的优缺点 #57

Open
ravencrown opened this issue Sep 1, 2019 · 0 comments
Open

第 39 题:vue响应式原理的优缺点 #57

ravencrown opened this issue Sep 1, 2019 · 0 comments

Comments

@ravencrown
Copy link
Owner

ravencrown commented Sep 1, 2019

vue 响应式的几点思考

响应式的描述

  1. 当 Vue Component render 函数被执行的时候, data 上会被 触碰(touch), 即被读, getter 方法会被调用, 此时 Vue 会去记录此 Vue component 所依赖的所有 data。(这一过程被称为依赖收集)

  2. data 被改动时(主要是用户操作), 即被写, setter 方法会被调用, 此时 Vue 会去通知所有依赖于
    此 data 的组件去调用他们的 render 函数进行更新。

  3. 通过 Observer 类,它的作用是给对象的属性添加 getter 和 setter,用于依赖收集和派发更新

  4. Observer 的构造函数,接下来会对 value 做判断,对于数组会调用 observeArray 方法,否则对纯对象调用 walk 方法。可以看到 observeArray 是遍历数组再次调用 observe 方法,而 walk 方法是遍历对象的 key 调用 defineReactive 方法

  5. Vue 在对 data 上的任何一个属性进行 reactive 化的时候,都会调用 defineReactive 函数,也就是说对于所有被 Vue reactive 化的属性来说都有一个 Dep 对象与之对应。那么这个 Dep 是做什么的呢?

  6. 通过这一节的分析,我们对 Vue 数据修改派发更新的过程也有了认识,实际上就是当数据发生变化的时候,触发 setter 逻辑,把在依赖过程中订阅的的所有观察者,也就是 watcher,都触发它们的 update 过程,这个过程又利用了队列做了进一步优化,在 nextTick 后执行所有 watcher 的 run,最后执行它们的回调函数。nextTick 是 Vue 一个比较核心的实现了

/**
 * Observer class that is attached to each observed
 * object. Once attached, the observer converts the target
 * object's property keys into getter/setters that
 * collect dependencies and dispatch updates.
 */
export class Observer {
  value: any;
  dep: Dep;
  vmCount: number; // number of vms that has this object as root $data

  constructor (value: any) {
    this.value = value
    this.dep = new Dep()
    this.vmCount = 0
    def(value, '__ob__', this)
    if (Array.isArray(value)) {
      const augment = hasProto
        ? protoAugment
        : copyAugment
      augment(value, arrayMethods, arrayKeys)
      this.observeArray(value)
    } else {
      this.walk(value)
    }
  }

  /**
   * Walk through each property and convert them into
   * getter/setters. This method should only be called when
   * value type is Object.
   */
  walk (obj: Object) {
    const keys = Object.keys(obj)
    for (let i = 0; i < keys.length; i++) {
      defineReactive(obj, keys[i])
    }
  }

  /**
   * Observe a list of Array items.
   */
  observeArray (items: Array<any>) {
    for (let i = 0, l = items.length; i < l; i++) {
      observe(items[i])
    }
  }
}

watcher 在哪定义?

依赖收集和依赖清空

Dep.target 的作用

Object.defineProperty 的优缺点

  1. vue 不能通过数组下标检测到变动
  2. 当你修改数组的长度时也是不能检测到
  3. 无法检测到对象属性的添加或删除
  4. Object.defineProperty 不能监听数组的变化,需要进行数组方法的重写

Proxy 代理

  1. Object.defineProperty无法监控到数组下标的变化,导致通过数组下标添加元素,不能实时响应;

  2. Object.defineProperty只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性
    值是对象,还需要深度遍历。Proxy可以劫持整个对象,并返回一个新的对象。

  3. Proxy不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。

Dep 、Watcher、Component、data之前的关系

参考

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant