vuex-undo v1.2.7
vuex-undo
A vuex efficient's plugin to record action of undo and redo". it will record vuex state change properties, don't replace whole state. when you dispatch an action of undo or redo, vuex-undo will change only the vuex state change properties.
why vuex-undo is performance effciency
for example
Demo Address: https://lixueshiaa.github.io/webtest/www/index.html#/h5-editor
const state = { // default vuex state
elementList: []
}
const mutations = {
// type : add(新增元素) editor(编辑元素) delete(删除元素)
['SET_ELEMENT_LIST_ITEM_CAPTURE'] (state, { type, element }) {
if (type == 'add') {
if (isPlainObject(element)) {
state.elementList.push(element)
} else if (isArray(element)) {
state.elementList = state.elementList.concat(element)
}
} else if (type == 'editor') {
const index = state.elementList.findIndex(item => item.elementId == element.elementId)
if (index > -1) {
state.elementList.splice(index, 1, element)
} else {
state.elementList.push(element)
}
} else if (type == 'delete') {
const index = state.elementList.findIndex(item => item.elementId == element.elementId)
if (index > -1) {
state.elementList.splice(index, 1)
}
}
}
}
const defaultElement = {
text: '默认元素',
elementId: 0,
style: {
color: 'black',
margin: 0,
position: 'absolute',
top: '60px',
left: '10px',
transform: 'none',
fontSize: '24px',
lineHeight: '1.5',
width: '150px',
height: '36px',
cursor: 'default'
}
}
const change_one = {
text: '默认元素',
elementId: 0,
style: {
color: 'black',
margin: 0,
position: 'absolute',
top: '104px', // changes property
left: '516px', // changes property
transform: 'none',
fontSize: '24px',
lineHeight: '1.5',
width: '150px',
height: '36px',
cursor: 'default'
}
}
const change_second = {
text: '默认元素',
elementId: 0,
style: {
color: 'black',
margin: 0,
position: 'absolute',
top: '104px',
left: '516px',
transform: 'rotateZ(76deg)', // changes property
transition: '',
fontSize: '24px',
lineHeight: '1.5',
width: '150px',
height: '36px',
cursor: 'default'
}
}
this.$store.commit('SET_ELEMENT_LIST_ITEM_CAPTURE', {type: 'add', element: defaultElement})
this.$store.commit('SET_ELEMENT_LIST_ITEM_CAPTURE', {type: 'editor', element: change_one})
this.$store.commit('SET_ELEMENT_LIST_ITEM_CAPTURE', {type: 'add', element: defaultElement})
// when you commit a mutation, vuex-undo will record the vuex state change properties like it(undo action list)
[{
"actionPath": [{
"kind": "A",
"path": ["elementList"],
"index": 0,
"item": {
"kind": "N",
"rhs": {
"text": "默认元素",
"elementId": 1,
"style": {
"color": "black",
"margin": 0,
"position": "absolute",
"top": "104px",
"left": "516px",
"transform": "rotateZ(76deg)",
"fontSize": "24px",
"lineHeight": "1.5",
"width": "150px",
"height": "36px",
"cursor": "default",
}
}
}
}]
}, {
"actionPath": [{
"kind": "E",
"path": ["elementList", 0, "style", "top"], // changes property path
"lhs": "60px", // previous value
"rhs": "104px" // current value
}, {
"kind": "E",
"path": ["elementList", 0, "style", "left"], // changes property path
"lhs": "10px", // previous value
"rhs": "516px" // current value
}]
}, {
"actionPath": [{
"kind": "E",
"path": ["elementList", 0, "style", "transform"],
"lhs": "none",
"rhs": "rotateZ(76deg)"
}]
}]
Install
npm i --save vuex-undo
Usage
How to use it in your store module
import Vue from 'vue'
import Vuex from 'vuex'
import undoable, { install } from 'vuex-undo'
Vue.use(Vuex)
const SETELEMENT = 'SETELEMENT' // define mormal mutation
// if you want to capture a mutation, you can add capture mark like it:
const SETELEMENT_CAPTURE = 'SETELEMENT_CAPTURE' // define a capture mutation
const state = {
// Define vuex state as normal
element: {
a: 1,
b: [2, 3]
}
}
const mutations = {
// Define vuex mutation as normal
SETELEMENT (state, element) {
state.element = element
},
// will be capture vuex mutation
SETELEMENT_CAPTURE (state, element) {
state.element = element
}
}
const actions = {
// Define vuex actions as normal
}
const getters = {
// Define vuex getters as normal
element: state => state.element
}
const moduleA = {
state: {
// Define vuex state as normal
...
},
mutations: {
// Define vuex mutation as normal
...
}
}
const moduleB = {
state: {
// Define vuex state as normal
...
},
mutations: {
// Define vuex mutation as normal
...
}
}
const modules = {
// Define vuex modules as normal
moduleA,
moduleB,
...
}
const store = new Vuex.Store(undoable({
state,
mutations,
actions,
getters,
modules
}))
const options = {
captureActionMask: '_CAPTURE', // Define capture mutation mark, default: '_CAPTURE'
store // vuex store example
}
Vue.use({ install }, options)
export default store
registry Vuex inside your app entrypoint
main.js
import store from './store'
import router from './router'
new Vue({
el: '#app',
store,
router,
render: h => {
return h(App)
}
})
How to use in your Vue components
<template>
<div>
<div class="opreate-block">
<button @click="undo" :disabled="!isVuexCaptureHaveUndo" type="button">undo</button>
<button @click="redo" :disabled="!isVuexCaptureHaveRedo" type="button">redo</button>
<button @click="normalMutations" type="button">normal mutation</button>
<button @click="captureMutations" type="button">capture mutation</button>
<button @click="captureContinuityMutations" type="button">capture continuity mutation</button>
</div>
<div>
<p>{{element.a}}</p>
<p :key="index" v-for="(it, index) in element.b">{{it}}<p>
</div>
</div>
</template>
import { mapGetters } from 'vuex'
export default {
data () {
return {
num: 0
}
},
computed: {
// isVuexCaptureHaveUndo : whether it have capture undo
// isVuexCaptureHaveRedo : whether it have capture redo
...mapGetters(['isVuexCaptureHaveUndo', 'isVuexCaptureHaveRedo', 'element'])
},
mounted () {
},
methods: {
undo () {
// if you want to undo mutations, you can dispatch an action "vuex_action_undo" to undo like it:
this.$store.dispatch('vuex_action_undo')
},
redo () {
// if you want to redo mutations, you can dispatch an action "vuex_action_redo" to undo like it:
this.$store.dispatch('vuex_action_redo')
},
normalMutations () {
// if you use mutation key haven't capture mutation mark, it will be not capture
this.$store.commit('SETELEMENT', {
a: this.num++,
b: [34]
})
},
captureMutations () {
// if you use mutation key have capture mutation mark, it will be capture
this.$store.commit('SETELEMENT_CAPTURE', {
a: this.num++,
b: [34, 434]
})
// if you already use mutation key have capture mutation mark, but you don't capture the mutation yet. you can use like it:
this.$store.commit('SETELEMENT_CAPTURE', {
a: this.num++,
b: [34, 434],
vuexCaptureMark: 'noCapture'
})
},
captureContinuityMutations () {
// if you are ues continuity mutations, the mutation's payload will be a object, it have one retain key "vuexCaptureMark" use to capture continuity mutation commit
this.$store.commit('SETELEMENT_CAPTURE', {
vuexCaptureMark: 'start', // set continuity mutation start capture mark
a: this.num++,
b: [34, 434]
})
let n = 10
const timer = setInterval(() => {
n--
// when you already capture continuity mutations start, vuex-undo will don't capture state property change to you commit every mutation
this.$store.commit('SETELEMENT_CAPTURE', {
a: this.num++
})
if (n < 0) {
clearInterval(timer)
this.$store.commit('SETELEMENT_CAPTURE', {
vuexCaptureMark: 'end', // set continuity mutations end capture mark
a: 44,
b: [34, 434 + this.num++]
})
}
}, 1000)
}
}
}
API
Options
captureActionMask: a String of capture mutation mark
store: a vuex store example
Computed properties
isVuexCaptureHaveUndo: undoes the last mutation
isVuexCaptureHaveRedo: redoes the last mutation
vuex actions
'vuex_action_undo' this.$store.dispatch('vuex_action_undo') // dispatch an undo action
'vuex_action_redo' this.$store.dispatch('vuex_action_redo') // despatch an redo action
Remarks
if you want more functions, you can add my QQ(920804994)
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago