首页 > 其他分享 >vue的观察者模式与发布订阅者模式(简单版)

vue的观察者模式与发布订阅者模式(简单版)

时间:2024-11-17 23:14:20浏览次数:3  
标签:订阅 vue Dep 观察者 模式 Watcher Vue

最近在背八股,然后看面试题的时候发现对于vue的响应式原理,观察者模式和发布订阅者模式好像都有,但是搞不清楚,所以看了几篇文章之后,根据GPT做了总结(简单版)

目录

1. 观察者模式(Observer Pattern)

观察者模式示例:

2. 发布-订阅模式(Publish-Subscribe Pattern)

发布-订阅模式示例:

3. Vue 的响应式系统结合了观察者模式和发布-订阅模式的特点

Vue 响应式系统的核心组成部分:

Vue 结合两种模式的实现过程:


1. 观察者模式(Observer Pattern)

  • 核心思想:对象之间通过直接引用来建立一种一对多的依赖关系。
  • 机制:观察者直接订阅被观察对象(通常称为“主体”)的变化。
  • 通知方式:当主体状态发生变化时,会自动通知所有观察者对象,观察者自行处理这些通知。
  • 缺点:耦合性较高,因为观察者需要直接依赖被观察的对象。
观察者模式示例:
// 被观察对象(主体)
class Subject {
  constructor() {
    this.observers = [];
  }
  
  // 添加观察者
  addObserver(observer) {
    this.observers.push(observer);
  }

  // 通知观察者
  notifyObservers() {
    this.observers.forEach(observer => observer.update());
  }
}

// 观察者
class Observer {
  update() {
    console.log('被通知了!');
  }
}

// 示例
const subject = new Subject();
const observer1 = new Observer();
const observer2 = new Observer();

subject.addObserver(observer1);
subject.addObserver(observer2);
subject.notifyObservers();  // 输出:'被通知了!' 两次

2. 发布-订阅模式(Publish-Subscribe Pattern)

  • 核心思想:通过第三方(发布中心)来解耦发布者和订阅者。
  • 机制:发布者和订阅者不直接联系,而是通过“事件中心”进行消息传递。
  • 通知方式:发布者将消息发布到中心,中心再广播给所有订阅者。
  • 优点:低耦合,发布者和订阅者彼此独立,可以动态添加订阅者,便于模块化。
发布-订阅模式示例:
// 发布-订阅中心
class EventEmitter {
  constructor() {
    this.events = {};
  }
  
  // 订阅
  on(event, listener) {
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(listener);
  }

  // 发布
  emit(event, ...args) {
    if (this.events[event]) {
      this.events[event].forEach(listener => listener(...args));
    }
  }
}

// 示例
const eventEmitter = new EventEmitter();

eventEmitter.on('message', (msg) => console.log('订阅者1收到消息:' + msg));
eventEmitter.on('message', (msg) => console.log('订阅者2收到消息:' + msg));

eventEmitter.emit('message', 'Hello, World!');  // 输出:两次不同订阅者收到消息

3. Vue 的响应式系统结合了观察者模式和发布-订阅模式的特点

在 Vue 中,数据的变动会触发相关视图的更新,同时组件之间的数据依赖和更新关系是自动建立的。其实现方式在 Vue 2 和 Vue 3 略有不同,但都融合了这两种模式的特性。

Vue 响应式系统的核心组成部分:
  • Dep:依赖收集器。Vue 中每个响应式属性都拥有一个Dep实例。Dep 的作用相当于发布-订阅模式的事件中心,负责依赖收集和通知更新。
  • Watcher:观察者。Watcher是 Vue 中的一个对象,用于跟踪数据的变化并重新渲染视图。当依赖的数据发生变化时,Watcher会被通知去更新视图。
Vue 结合两种模式的实现过程:
  1. 观察者模式的体现

    • Vue 的 Watcher通过依赖收集直接订阅了数据的变化。
    • 当数据变化时,通过 Dep 触发 Watcher的更新,Watcher再去触发组件的重新渲染。
    • 每个 Watcher知道自己依赖了哪些数据属性。
  2. 发布-订阅模式的体现

    • Dep 相当于一个中介,负责维护所有依赖于数据的 Watcher,并在数据变化时广播给所有 Watcher。
    • 数据和视图之间的关系通过 Dep 解耦,避免了组件和数据之间的直接依赖关系,使得更新逻辑更灵活。

Vue2响应式的简单实现:

class Dep {
  constructor() {
    this.subscribers = new Set();
  }

  // 添加订阅者
  depend() {
    if (activeWatcher) {
      this.subscribers.add(activeWatcher);
    }
  }

  // 通知所有订阅者更新
  notify() {
    this.subscribers.forEach(sub => sub.update());
  }
}

class Watcher {
  constructor(fn) {
    this.fn = fn;
    activeWatcher = this; // 当前观察者
    fn(); // 触发依赖收集
    activeWatcher = null;
  }

  update() {
    this.fn();
  }
}

function reactive(obj) {
  Object.keys(obj).forEach(key => {
    let internalValue = obj[key];
    const dep = new Dep();

    Object.defineProperty(obj, key, {
      get() {
        dep.depend(); // 收集依赖
        return internalValue;
      },
      set(newValue) {
        internalValue = newValue;
        dep.notify(); // 触发更新
      }
    });
  });
  return obj;
}

// 示例
let activeWatcher = null;
const data = reactive({ price: 5, quantity: 2 });
new Watcher(() => {
  console.log('总价更新:', data.price * data.quantity);
});

data.price = 10;  // 输出:'总价更新: 20'

一位博主的Vue2源码浅析文章:

前端 - Vue2源码-响应式原理浅析 - Vue源码分析 - SegmentFault 思否

标签:订阅,vue,Dep,观察者,模式,Watcher,Vue
From: https://blog.csdn.net/shadowflies/article/details/143712548

相关文章