美文网首页
vue 2x源码(四)--- Observer

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

作者: azothaw | 来源:发表于2017-03-01 23:21 被阅读61次

    绑定数据应该是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

          本文链接:https://www.haomeiwen.com/subject/wmgcgttx.html