A Vue.js plugin that allows you to undo or redo a mutation.
The building of this plugin is documented in the article Create A Vuex Undo/Redo For VueJS
There's also a demo in this Codepen. The source code for the demo is here.
npm i --save-dev vuex-undo-redo
<script
type="text/javascript"
src="node_modules/vuex-undo-redo/dist/vuex-undo-redo.min.js"
></script>
import VuexUndoRedo from 'vuex-undo-redo';
You must, of course, have the Vuex plugin installed, and it must be installed before this plugin.
The store needs then to be passed as an options to the plugin when installing:
let store = new Vuex.Store({
state: {
myVal: null
},
mutations: {
// ...
}
});
Vue.use(VuexUndoRedo, { $store: store });
The plugin works by re-initializing the Store state to an "empty state". In order to do so, you need to provide the empty state for your data (and modules, if any). This can be done in 3 different ways:
- You can pass the empty state as a plain JS object, through the plugin option:
Vue.use(VuexUndoRedo, {
$store: store,
emptyState: {
myval: null
}
});
- If you want to add more logic to the state emptying, you can pass a function through the plugin option:
Vue.use(VuexUndoRedo, {
$store: store,
emptyState: (undoRedoState, store) => {
store.replaceState(
Object.assign({}, undoRedoState, {
myVal: 0
})
);
}
});
The function can take 2 arguments:
- the
undoRedoState
object, containing all state created by the plugin (so that you can merge it with your state) ; - the
store
instance.
- You can implement yourself the
emptyState
mutation, which should revert the store back to the initial state e.g.:
let store = new Vuex.Store({
state: {
myVal: null
},
mutations: {
emptyState(state) {
this.replaceState({
myval: null,
undoRedo: { lastUndoRedoTag: null }
});
}
}
});
Vue.use(VuexUndoRedo, { $store: store });
Note: when using this method, you must reset the state.undoRedo
module yourself. Otherwise, the Tag feature will not work.
Occasionally, you may want to perform mutations without including them in the undo history (say you are working on an image editor and the user toggles grid visibility - you probably do not want this in undo history). The plugin has an ignoredMutations
setting to leave these mutations out of the history:
Vue.use(VuexUndoRedo, { $store: store, ignoreMutations: ['toggleGrid'] });
It's worth noting that this only means the mutations will not be recorded in the undo history. You must still manually manage your state object in the emptyState
option:
emptyState(state) {
this.replaceState({ myval: null, showGrid: state.showGrid });
}
From version 2.0.0
, you can now undo a set of changes using tags.
You first need to tag a version of the store state through the special VuexUndoRedo.TAG_UNDO_MUTATION
mutation with a given string. Then, you can later call undo('MyTag')
to undo the mutations between the myTag
commit and now.
This is useful for instance if you want to implement a view / edit mode switch: you can tag your state when you enter edit mode, and undo everything from the tag if user hits "Cancel" instead of "Save".
The tagging is done using a simple commit to the store:
import { TAG_UNDO_MUTATION } from 'vuex-undo-redo';
this.$store.commit(TAG_UNDO_MUTATION, 'MyTag');
And if you want to undo everything done between this commit and the present state, you might just call:
this.undo('MyTag');
If the same string is used multiple times (say n
), the plugin will first undo mutations between the last instance (n
) of this tag and now. The next undo
called with the same tag string will then cancel then mutations between n-1
and now, etc.
$store
(mandatory) The newly created store
emptyState
(mandatory if you plan on using the Tag feature, optional otherwise) A method or object to handle the empty state.
ignoredMutations
(optional) An array of mutations that the plugin will ignore
canUndo
a boolean which tells you if the state is undo-able
canRedo
a boolean which tells you if the state is redo-able
undo
undoes the last mutation
undo(tagName)
undoes the mutations from the given tagName
redo
redoes the last mutation