image.png

it defines a one-to-many dependency between objects. When one object (the subject) changes state, all its dependents (observers) are notified and updated automatically.

// Observable.js

class Observable {
  constructor() {
    this.observers = [];
  }

  subscribe(f) {
    this.observers.push(f);
  }

  unsubscribe(f) {
    this.observers = this.observers.filter(subscriber => subscriber !== f);
  }

  notify(data) {
    this.observers.forEach(observer => observer(data));
  }
}

export default new Observable();

or as function: (but this may have duplicated functions to subscribers)

// Observable.js
export default {
  subscribers: [],
  subscribe(callback) {
    this.subscribers.push(callback);
  },
  notify(data) {
    this.subscribers.forEach((callback) => callback(data));
  }
};

Template File:

<template>
  <div class="App">
    <button @click="handleClick">Click me!</button>
    <label>
      <input type="checkbox" @change="handleToggle" />
      Toggle me!
    </label>
  </div>
</template>

<script setup>
import { onMounted } from 'vue';
import { useToast } from 'vue-toastification';
import observable from './Observable';

const toast = useToast();

function handleClick() {
  observable.notify("User clicked button!");
}

function handleToggle() {
  observable.notify("User toggled switch!");
}

function logger(data) {
  console.log(`${Date.now()} ${data}`);
}

function toastify(data) {
  toast(data);
}

onMounted(() => {
  observable.subscribe(logger);
  observable.subscribe(toastify);
});
</script>

<style>
.App {
  padding: 1rem;
}
button {
  margin-right: 1rem;
}
</style>

Now both logger and toastify callbacks are called with either the handleToggle or handleClick