必须做作业4:vue中观察者模式解析

一、观察者模式简介

  观察者模式是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。(参考链接:https://zh.wikipedia.org/wiki/%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F)

  

  

用途

  • 当抽象个体有两个互相依赖的层面时。封装这些层面在单独的对象内将可允许程序员单独地去变更与重复使用这些对象,而不会产生两者之间交互的问题。
  • 当其中一个对象的变更会影响其他对象,却又不知道多少对象必须被同时变更时。
  • 当对象应该有能力通知其他对象,又不应该知道其他对象的实做细节时。

我的理解是:被观察的对象存有一个观察者表,表中存储了所有已注册的观察者对象,当对象发生状态变化时,会调用通知方法通知到每个已注册的观察者。

      被观察对象有注册方法和解绑方法,注册方法的作用是注册一个新的观察者对象到观察者表;解绑方法是从观察者表中移除某个观察者对象。

      观察者关注被观察者,且当观察者广播状态变化时,观察者应执行其应对状态变化的方法。

      举例来说,模式上类似于QTCreator中的signal-slot关系,一个signal唤醒其绑定的slot,执行slot方法。观察者模式可以在对状态改变比较敏感的情况下使用,例如乘车告示等。

 

二、vue中的观察者模式分析

  (GitHub路径:https://github.com/vuejs/vue/blob/dev/src/core/observer/dep.js#L37)

  

/* @flow */

import type Watcher from './watcher'
import { remove } from '../util/index'
import config from '../config'

let uid = 0

/**
 * A dep is an observable that can have multiple
 * directives subscribing to it.
 */
export default class Dep {
  static target: ?Watcher;
  id: number;
  subs: Array<Watcher>;

  constructor () {
    this.id = uid++
    this.subs = []
  }

  addSub (sub: Watcher) {
    this.subs.push(sub)
  }

  removeSub (sub: Watcher) {
    remove(this.subs, sub)
  }

  depend () {
    if (Dep.target) {
      Dep.target.addDep(this)
    }
  }

  notify () {
    // stabilize the subscriber list first
    const subs = this.subs.slice()
    if (process.env.NODE_ENV !== 'production' && !config.async) {
      // subs aren't sorted in scheduler if not running async
      // we need to sort them now to make sure they fire in correct
      // order
      subs.sort((a, b) => a.id - b.id)
    }
    for (let i = 0, l = subs.length; i < l; i++) {
      subs[i].update()
    }
  }
}

// the current target watcher being evaluated.
// this is globally unique because there could be only one
// watcher being evaluated at any time.
Dep.target = null
const targetStack = []

export function pushTarget (_target: ?Watcher) {
  if (Dep.target) targetStack.push(Dep.target)
  Dep.target = _target
}

export function popTarget () {
  Dep.target = targetStack.pop()
}

  如demo所示,被观察类Dep拥有的方法:

  addSub(sub:Watcher):    注册方法,添加一个观察者对象,代码体现为push一个sub对象进入Array subs中;

  removeSub(sub:Watcher):   解绑方法,从Array subs中移除传参的sub对象;

  notify():    通知方法,若本对象发生变化,将变化通知至subs Array中的所有对象。

 

posted @ 2018-10-23 15:02  LoginAsAdministrator  阅读(519)  评论(0)    收藏  举报