vue 数据响应模式浅析

       对于vue的数据响应模式,不外乎采用设计模式中的观察者模式.即为一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应。      

       那么在vue中,我们都知道 data,props发生变化会让页面重新render等.那么他们必然是观察者模式中的观察对象,即被观察者.那么我们来看一下一个普通的data,vue中对它做了什么处理.        在observer/index.js,核心应该是函数  defineReactive() .在这个函数里面,对object的set和get方法进行了重写.

Object.defineProperty(obj, key, {
  enumerable: true,
  configurable: true,
  get: function reactiveGetter () {
    const value = getter ? getter.call(obj) : val
    if (Dep.target) {
      // 为dept增加watch
      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
    /* eslint-disable no-self-compare */
    if (newVal === value || (newVal !== newVal && value !== value)) {
      return
    }
    /* eslint-enable no-self-compare */
    if (process.env.NODE_ENV !== 'production' && customSetter) {
      customSetter()
    }
    if (setter) {
      setter.call(obj, newVal)
    } else {
      val = newVal
    }
    childOb = !shallow && observe(newVal)
    dep.notify()
  }

那么这个时候又引入了新的东东,Dep,如果此时和Dep一起说,很容易云里雾里,所以我们暂时先不理会Dep,只要知道在set和get的时候调用Dep搞了一些事情就好了.其实这个构造观察目标的过程很简单,无非就是遍历来重写他的get,set方法,以及遇到对象时深度遍历而已.      

        那么接下来我们就来看观察者watcher.我们在使用过程中,我们在使用过程中.最明显的创建 watch便是创建了观察者.compute,包括render方法,都是创建了watcher,所以,创建watcher过程中.

expOrFn: string | Function,

它可能是一个string或者一个function.在watcher中,

addDep (dep: Dep)
cleanupDeps( )

等方法均是对依赖(别观察者)的增删.update则是响应被观察者的变化.无非是 函数 的话执行一遍.值的话取值,有回调的执行回调.也是很简单.

        那么现在还缺少一个轴,将观察者和被观察者链接到一起的轴.这时dep这个类出现了.每一个观察对象都拥有一个dep的实例.而这个实例中,又存储了所有的观察者.这样就形成了观察者模式中的一对多关系.而 notify方法实际上就是通知它所有的watcher进行update操作.(为什么要这么个东东,而不直接wacher和observer关联,其实我也不知道啦啦啦~~~).

        上面介绍的东西实质上都平淡无奇,很好理解.那么最后一个问题来了,observer如何与其对应的watcher关联起来.那么这时候就体现出作者的构思巧妙了. 实际上wacher 在create 的过程中,如果是function,会执行一遍,如果是exp,将它构造成一个简单函数:

// 从vm中取到值
return function (obj) {
  for (let i = 0; i < segments.length; i++) {
    if (!obj) return
    obj = obj[segments[i]]
  }
  return obj
}

      在执行之前,调用

pushTarget(this)

      也就是将自身(watcher)暂存到Dep.target上,执行过程中,如果observer的get方法,那么会执行get方法中

dep.depend()

observer会把watcher加入到自己的dep队列中,成为自身观察者之一.十分简单,但是确实有效.

       基本分析完毕.

 

转载于:https://my.oschina.net/vqishiyu/blog/1588186

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值