Skip to content

Vuex

Core

observer

js
export const createObserver = () => {
  const map = new Map();

  return {
    notify: createNotify(map),
    observe: createObserve(map)
  };
};

const createNotify = (map) => (key, value) => {
  const fns = map.get(key);
  fns.forEach(fn => fn(value))
};

const createObserve = (map) => (key, fn) => {
  map.has(key) || map.set(key, new Set());

  const observers = map.get(key);
  observers.add(fn);
};

vuex

js
import {createObserver} from './observer.js';

export const createStore = ({state, mutation, actions}) => {
  const observer = createObserver();
  const innerState = ref(state);

  const commit = (mutationName, payload) => {
    const oldValue = innerState.value;
    const newValue = mutation[mutationName](oldValue, payload);

    innerState.value = newValue;
    detectMutation(oldValue, newValue);
  };
  const detectMutation = (oldValue, newValue) => {
    Object
      .keys(oldValue)
      .forEach((key) => {
        if (oldValue[key] !== newValue[key]) {
          observer.notify(key, newValue[key])
        }
      });
  };

  const context = {
    commit,
    get state () {
      return innerState.value;
    },
  };

  const dispatch = (actionName, payload) => {
    actions[actionName](context, payload);
  };

  return {
    dispatch,
    observe: observer.observe,
  }
};

const ref = (value) => ({value});

Consumer

store module

js
import {createStore} from './core/vuex.js';

export const store = createStore({
  state: {
    presentation: null,
    name: '',
    age: '',
  },
  mutation: {
    mutatePresentation: (state, presentation) => {
      return {...state, presentation}
    },
    mutateName: (state, name) => {
      return {...state, name}
    },
    mutateAge: (state, age) => {
      return {...state, age}
    }
  },
  actions: {
    updatePresentation: (context, payload) => {
      context.commit('mutatePresentation', payload);
    },
    updatePersonInfo: (context, {name, age}) => {
      console.log(context.state);
      context.commit('mutateName', name);
      context.commit('mutateAge', age);
    }
  }
});

index

js
import {store} from './store.js'

store.observe('presentation', (presentation) => {
  console.log(presentation);
});
store.observe('name', (name) => {
  console.log(`My Name is ${name}`);
});
store.observe('age', (age) => {
  console.log(`I'm ${age}`);
});

store.dispatch('updatePersonInfo', {
  name: 'Peter',
  age: 10,
});
store.dispatch('updatePresentation', '<div></div>');