Vuex自定义插件实现 undo-redo

1,065 阅读1分钟

Vuex插件

Vuex.store构造器选项中包含plugins插件, 其值为数组,包含应用在 store 上的插件方法。这些插件直接接收 store 作为唯一参数,可以监听 mutation(用于外部地数据持久化、记录或调试)或者提交 mutation (用于内部数据,例如 websocket 或 某些观察者)

new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  modules: {},
  plugins: [function]
});

Vuex 订阅mutations

Vuex.store实例属性中包含subscribe, 订阅 store 的 mutation。handler 会在每个 mutation 完成后调用,接收 mutation 和经过 mutation 后的状态作为参数

const stop = store.subscribe((mutation, state) => {
  console.log(mutation.type)
  console.log(mutation.payload)
})
// stop() // 停止订阅

撤销栈

const cloneDeep = require("clone-deep");
export default class UndoRedoHistory {
  store;
  history = [];
  currentIndex = -1;

  init(store) {
    this.store = store;
  }

  addState(state) {
    if (this.currentIndex + 1 < this.history.length) {
      this.history.splice(this.currentIndex + 1);
    }
    this.history.push(state);
    this.currentIndex++;
  }

  undo() {
    const prevState = this.history[this.currentIndex - 1];
    if (!prevState) return;
    this.store.replaceState(cloneDeep(prevState));
    this.currentIndex--;
  }

  redo() {
    const nextState = this.history[this.currentIndex + 1];
    if (!nextState) return;
    this.store.replaceState(cloneDeep(prevState));
    this.currentIndex++;
  }
}

Vuex插件实现

import UndoRedoHistory from "../utils/UndoRedoHistory";
import Vue from "vue";

const cloneDeep = require("clone-deep");

const undoRedoHistory = new UndoRedoHistory();

Vue.prototype.$undoRedoHistory = undoRedoHistory;

window.undoRedoHistory = undoRedoHistory; // 测试

const undoRedoPlugin = store => {
  undoRedoHistory.init(store);
  store.subscribe((mutation, state) => {
    undoRedoHistory.addState(cloneDeep(state));
  });
};
export default undoRedoPlugin;

Vuex中使用插件

import Vue from "vue";
import Vuex from "vuex";
import undoRedoPlugin from "../plugins/undoRedoPlugin";
Vue.use(Vuex);

export default new Vuex.Store({
  state: {},
  mutations: {},
  modules: {},
  plugins: [undoRedoPlugin]
});

参考:

API | Vuex

Going back to States like Undo Redo on Vue.js vuex