1.2.7 • Published 3 years ago

vuex-undo v1.2.7

Weekly downloads
-
License
ISC
Repository
-
Last release
3 years ago

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)

1.2.7

3 years ago

1.2.6

3 years ago

1.2.0

3 years ago

1.1.9

3 years ago

1.1.8

3 years ago

1.1.7

3 years ago

1.2.5

3 years ago

1.1.6

3 years ago

1.2.4

3 years ago

1.1.5

3 years ago

1.2.3

3 years ago

1.2.2

3 years ago

1.2.1

3 years ago

1.1.4

3 years ago

1.1.3

3 years ago

1.1.1

3 years ago

1.1.2

3 years ago

1.0.2

3 years ago

1.1.0

3 years ago

1.0.1

3 years ago

1.0.0

3 years ago

1.0.9

3 years ago

1.0.8

3 years ago

1.0.7

3 years ago

1.0.6

3 years ago

1.0.5

3 years ago

1.0.4

3 years ago

1.0.3

3 years ago

0.0.1

4 years ago