vue 2x源码(四)--- Observer

绑定数据应该是vue2x最核心的代码之一了,1x版本是借鉴了ng1x的脏检查,2x现在改成了观察者来实现这个功能。

首先介绍这里用到的几个核心函数

  • getOwnPropertyNames 获取自身属性名(注意这里都是自身)
  • getOwnPropertyDescriptor 获取自身属性值
  • defineProperty 定义属性,可以set,可以get

1、首先获取keys

const arrayKeys = Object.getOwnPropertyNames(arrayMethods)

2、构造函数

判断是数组还是复合数组 还是普通对象,普通直接观察,数组遍历一次,复合数组深度遍历,遍历完返回新的observer对象,直到可以绑定,这里是一个迭代。。

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)
    }
  }

3、终于可以绑定了,到了walk方法

walk遍历了属性然后传到绑定函数(这里为啥不直接for in。。)

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

4、finally。。。

变量的操作都会走setget ,set的时候同时渲染页面,get的时候同时绑定数据。

export function defineReactive (
  obj: Object,
  key: string,
  val: any,
  customSetter?: Function
) {
  const dep = new Dep()

  const property = Object.getOwnPropertyDescriptor(obj, key)
  if (property && property.configurable === false) {
    return
  }

  // cater for pre-defined getter/setters
  const getter = property && property.get
  const setter = property && property.set

  let childOb = observe(val)
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter () {
      const value = getter ? getter.call(obj) : val
      if (Dep.target) {
        dep.depend()
        if (childOb) {
          childOb.dep.depend()
        }
        if (Array.isArray(value)) {
          dependArray(value)
        }
      }
      return value
    },
    set: function reactiveSetter (newVal) {
      const value = getter ? getter.call(obj) : val
      if (newVal === value) {
        return
      }
      if (process.env.NODE_ENV !== 'production' && customSetter) {
        customSetter()
      }
      if (setter) {
        setter.call(obj, newVal)
      } else {
        val = newVal
      }
      childOb = observe(newVal)
      dep.notify()
    }
  })
}

你可能感兴趣的:(vue 2x源码(四)--- Observer)