【core/observer】之Observer类

   日期:2020-07-08     浏览:92    评论:0    
核心提示:export class Observer { value: any; dep: Dep; vmCount: number; // 具有该对象作为根$data的vm的数量 constructor (value: any) { this.va

export class Observer {
  value: any;
  dep: Dep;
  vmCount: number; // 具有该对象作为根$data的vm的数量

  constructor (value: any) {
    this.value = value
    this.dep = new Dep() // 用来存放array的依赖
    this.vmCount = 0
    
    def(value, '__ob__', this) 
    if (Array.isArray(value)) {
      if (hasProto) {
        protoAugment(value, arrayMethods)
      } else {
        copyAugment(value, arrayMethods, arrayKeys)
      }
      this.observeArray(value)
    } else {
      this.walk(value)
    }
  }

  
  walk (obj: Object) {
    const keys = Object.keys(obj)
    for (let i = 0; i < keys.length; i++) {
      defineReactive(obj, keys[i])
    }
  }

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

概述:

对于Observer类,这个类,就是给每一个对象,添加一个 __ob__ 属性,并且把这个对象,变成getter/setter形式。变成这样的形式呢,会方便收集依赖,并且在数据发生变化的时候,通知各个依赖。

相关方法

  1. Dep
    类里面使用this.dep = new Dep(),是为了存放数组的依赖,因为数组在getter的时候收集依赖,在拦截器里触发依赖,将数组的依赖放在Observer的实例上,是为了让数组的getter和拦截器中都能访问到。

  2. def()
    这个方法,是用来处理value,给它添加一个__ob__的属性,这个属性的值就是当前Observer的实例,因为数组的依赖保存在Observer的实例上,所以添加这个值,就可以在拦截器中访问Observer实例,并拿到相应的依赖。


function def (obj, key, val, enumerable) {
  Object.defineProperty(obj, key, {
    value: val,
    enumerable: !!enumerable,
    writable: true,
    configurable: true
  });
}

// Observer 类中
def(value, '__ob__', this) 
  1. 判断value是对象还是数组,如果是对象的话,就走walk方法,walk方法就是把object自身有的属性遍历一边,然后用defineReactive()方法全部转换成getter/setter形式
  2. 如果是数组对象,就需要先判断一下,浏览器能不能支持__proto__这个属性,为什么要判断这个属性?因为数组的某些原型中的方法,需要覆盖,通过判断hasProto来用两种方法来处理覆盖value原型的功能,支持__proto__,使用protoAugment()函数覆盖原型,如果不支持,则调用copyAugment()函数将拦截器中的方法挂载到vulue上。

function protoAugment (target, src: Object) {
  
  target.__proto__ = src
  
}


function copyAugment (target: Object, src: Object, keys: Array<string>) {
  for (let i = 0, l = keys.length; i < l; i++) {
    const key = keys[i]
    def(target, key, src[key])
  }
}
  1. observeArray()方法
    循环Array中的每一项,执行observe函数来侦测变化,通过observe函数,将数组中的每一个元素都执行一遍new Observer()
  2. observe()

export function observe (value: any, asRootData: ?boolean): Observer | void {
  // 不是对象或者不是VNode的实例,就返回
  if (!isObject(value) || value instanceof VNode) {
    return
  }
  let ob: Observer | void
  // 有observer实例就返回该实例
  if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
    ob = value.__ob__
  } else if (
    shouldObserve &&
    !isServerRendering() &&
    (Array.isArray(value) || isPlainObject(value)) &&
    Object.isExtensible(value) &&
    !value._isVue
  ) {
    ob = new Observer(value)
  }
  if (asRootData && ob) {
    ob.vmCount++
  }
  // 否则返回新增的实例
  return ob
}
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服