Vuex Data Persistence数据持久化

In one of my frontend project using VueJS, there is a need to maintain run-time data in javascript to local hardware so that these data will not be lost in case of a page refreshing. This requirement can be saying in another way – data persistence is required. Since the diversity of frontend environment, there are many stuff can be employed to save your run-time data. For example, if you use react-native, you can use one of React Native’s API called AsyncStorage; if you are written html webpage, the Html api sessionStorage, localStorage and cookie can all be employed. And today we are going to employ localStorage, we’re going to talk about data persistence in webpage developed using VueJS.

First, let’s talk about the premise: my project used vue 2.2.1, vuex 2.2.1, and vuex-persist 0.1.8. To use vuex-persist 0.1.8, the official npm page says that Vue of version equal to or higher than 2.0 , vuex of version equal to or higher than 2.1 are required.

Vuex-persist is used as a plugin of vuex. In my program, I create the store using code like below (simplified and many code is removed):

// import Vue from 'vue'
import Vuex from 'vuex'
import { merge } from './utils'
import { config } from './mode'
import mock from '../mock'
import VuexPersistence from 'vuex-persist'

// 用于使用script标签加载window.Vuex,Vuex会被自动安装,无需手动安装
// Vue.use(Vuex)

const state = {
  config,
  mock,
  states: {
    // other code here
    alertingOkCallback () {},
    alertingCancelCallback () {},
    // other code here
  },
  wechat: {},
  user: {},
  car: {},
  order: {},
  options: {
    orderStatus: [
      { value: '0', text: '核保中', belong: '核保中' },
      { value: '1', text: '已取消', belong: '已取消' },
      { value: '2', text: '质检失败', belong: '核保中' },
      { value: '3', text: '核保失败', belong: '核保失败' },
      { value: '4', text: '待核保', belong: '核保中' },
      // { value: '5', text: '待质检', belong: '核保中' },
      { value: '5', text: '待缴费', belong: '核保中' },
      { value: '6', text: '已质检', belong: '核保中' },
      { value: '7', text: '待解付', belong: '核保成功' },
      { value: '8', text: '待出单', belong: '核保成功' },
      { value: '9', text: '已出单', belong: '已完成' },
      { value: '10', text: '已分配快递员', belong: '已完成' },
      { value: '11', text: '已取单', belong: '已完成' },
      { value: '12', text: '配送成功', belong: '已完成' },
      { value: '13', text: '配送失败', belong: '已完成' },
      { value: '14', text: '已退单', belong: '已取消' },
      { value: '15', text: '代垫付', belong: '核保成功' },
      { value: '16', text: '转人工', belong: '核保中' }
    ],
    certificateType: [
      { value: '1', text: '身份证' },
      { value: '2', text: '组织机构代码证' },
      { value: '3', text: '护照' },
      { value: '4', text: '军官证' },
      { value: '5', text: '港澳回乡证或台胞证' },
      { value: '6', text: '其他' },
      { value: '7', text: '港澳通行证' }
    ]
  }
}

const initialStateString = JSON.stringify(state)

const getters = {
  config: state => state.config,
  mock: state => state.mock,
  states: state => state.states,
  user: state => state.user,
  wechat: state => state.wechat,
  car: state => state.car,
  order: state => state.order,
  options: state => state.options
}

const mutations = {
  setStates (state, options) { merge(state.states, options) },
  setUser (state, options) { merge(state.user, options) },
  setWechat (state, options) { merge(state.wechat, options) },
  setCar (state, options) { merge(state.car, options) },
  setOrder (state, options) { merge(state.order, options) },
  resetAllStoreInfo (state, options) {
    merge(state, (() => {
      const originalState = JSON.parse(initialStateString)
      return {
        states: originalState.states,
        // user: originalState.user,
        wechat: originalState.wechat,
        car: {
          ...originalState.car,
          ownerName: state.car.ownerName,
          plateHeader: state.car.plateHeader,
          plateBody: state.car.plateBody
        },
        order: originalState.order
      }
    })())
  }
}

const actions = {
  load: ({ commit }, bool) => commit('setStates', {
    isLoading: bool
  }),
  roar: ({ commit }, { text, callback }) => commit('setStates', {
    isRoaring: true,
    roaringText: text,
    roaringCallback: callback || null
  }),
  alert: ({ commit }, { text, callback }) => commit('setStates', {
    isAlerting: true,
    alertingText: text,
    alertingOkCallback () {
      callback && callback()
      commit('setStates', { isAlerting: false })
    },
    alertingCancelCallback: null
  }),
  confirm: ({ commit }, { text, okCallback, cancelCallback }) => commit('setStates', {
    isAlerting: true,
    alertingText: text,
    alertingOkCallback () {
      okCallback && okCallback()
      commit('setStates', { isAlerting: false })
    },
    alertingCancelCallback () {
      cancelCallback && cancelCallback()
      commit('setStates', { isAlerting: false })
    }
  }),
  wait: ({ commit }, bool) => commit('setStates', {
    isWaiting: bool
  }),
  present: ({ commit }, val) => commit('setStates', {
    presenting: val
  })
}

const vuexLocal = new VuexPersistence({
  storage: window.localStorage,
  reducer: state => ({
    user: state.user,
    wechat: state.wechat,
    car: state.car,
    order: state.order
  }),
  filter: (mutation) => (
    mutation.type === 'setUser' ||
    mutation.type === 'setWechat' ||
    mutation.type === 'setCar' ||
    mutation.type === 'setOrder' ||
    mutation.type === 'resetAllStoreInfo'
  )
})

export default new Vuex.Store({
  state,
  getters,
  actions,
  mutations,
  plugins: [vuexLocal.plugin]
})

// import Vue from 'vue'
import Vuex from 'vuex'
import { merge } from './utils'
import { config } from './mode'
import mock from '../mock'
import VuexPersistence from 'vuex-persist'
 
// 用于使用script标签加载window.Vuex,Vuex会被自动安装,无需手动安装
// Vue.use(Vuex)
 
const state = {
  config,
  mock,
  states: {
    // other code here
    alertingOkCallback () {},
    alertingCancelCallback () {},
    // other code here
  },
  wechat: {},
  user: {},
  car: {},
  order: {},
  options: {
    orderStatus: [
      { value: '0', text: '核保中', belong: '核保中' },
      { value: '1', text: '已取消', belong: '已取消' },
      { value: '2', text: '质检失败', belong: '核保中' },
      { value: '3', text: '核保失败', belong: '核保失败' },
      { value: '4', text: '待核保', belong: '核保中' },
      // { value: '5', text: '待质检', belong: '核保中' },
      { value: '5', text: '待缴费', belong: '核保中' },
      { value: '6', text: '已质检', belong: '核保中' },
      { value: '7', text: '待解付', belong: '核保成功' },
      { value: '8', text: '待出单', belong: '核保成功' },
      { value: '9', text: '已出单', belong: '已完成' },
      { value: '10', text: '已分配快递员', belong: '已完成' },
      { value: '11', text: '已取单', belong: '已完成' },
      { value: '12', text: '配送成功', belong: '已完成' },
      { value: '13', text: '配送失败', belong: '已完成' },
      { value: '14', text: '已退单', belong: '已取消' },
      { value: '15', text: '代垫付', belong: '核保成功' },
      { value: '16', text: '转人工', belong: '核保中' }
    ],
    certificateType: [
      { value: '1', text: '身份证' },
      { value: '2', text: '组织机构代码证' },
      { value: '3', text: '护照' },
      { value: '4', text: '军官证' },
      { value: '5', text: '港澳回乡证或台胞证' },
      { value: '6', text: '其他' },
      { value: '7', text: '港澳通行证' }
    ]
  }
}
 
const initialStateString = JSON.stringify(state)
 
const getters = {
  config: state => state.config,
  mock: state => state.mock,
  states: state => state.states,
  user: state => state.user,
  wechat: state => state.wechat,
  car: state => state.car,
  order: state => state.order,
  options: state => state.options
}
 
const mutations = {
  setStates (state, options) { merge(state.states, options) },
  setUser (state, options) { merge(state.user, options) },
  setWechat (state, options) { merge(state.wechat, options) },
  setCar (state, options) { merge(state.car, options) },
  setOrder (state, options) { merge(state.order, options) },
  resetAllStoreInfo (state, options) {
    merge(state, (() => {
      const originalState = JSON.parse(initialStateString)
      return {
        states: originalState.states,
        // user: originalState.user,
        wechat: originalState.wechat,
        car: {
          ...originalState.car,
          ownerName: state.car.ownerName,
          plateHeader: state.car.plateHeader,
          plateBody: state.car.plateBody
        },
        order: originalState.order
      }
    })())
  }
}
 
const actions = {
  load: ({ commit }, bool) => commit('setStates', {
    isLoading: bool
  }),
  roar: ({ commit }, { text, callback }) => commit('setStates', {
    isRoaring: true,
    roaringText: text,
    roaringCallback: callback || null
  }),
  alert: ({ commit }, { text, callback }) => commit('setStates', {
    isAlerting: true,
    alertingText: text,
    alertingOkCallback () {
      callback && callback()
      commit('setStates', { isAlerting: false })
    },
    alertingCancelCallback: null
  }),
  confirm: ({ commit }, { text, okCallback, cancelCallback }) => commit('setStates', {
    isAlerting: true,
    alertingText: text,
    alertingOkCallback () {
      okCallback && okCallback()
      commit('setStates', { isAlerting: false })
    },
    alertingCancelCallback () {
      cancelCallback && cancelCallback()
      commit('setStates', { isAlerting: false })
    }
  }),
  wait: ({ commit }, bool) => commit('setStates', {
    isWaiting: bool
  }),
  present: ({ commit }, val) => commit('setStates', {
    presenting: val
  })
}
 
const vuexLocal = new VuexPersistence({
  storage: window.localStorage,
  reducer: state => ({
    user: state.user,
    wechat: state.wechat,
    car: state.car,
    order: state.order
  }),
  filter: (mutation) => (
    mutation.type === 'setUser' ||
    mutation.type === 'setWechat' ||
    mutation.type === 'setCar' ||
    mutation.type === 'setOrder' ||
    mutation.type === 'resetAllStoreInfo'
  )
})
 
export default new Vuex.Store({
  state,
  getters,
  actions,
  mutations,
  plugins: [vuexLocal.plugin]
})

Attention
Please be aware of that some of the code above is not written in the best or at least better practice, for example, state.options is just static data, and these data can be separated to a new file and not included in the state variable, because it’s not necessary to monitoring these data through vuex. They are listed here just for intention purpose.)

Analyse
First, let’s analyze that which data in variable state should be keep persist – that’s to say – which data should be saved to local hardware through Html5 api localStorage.

You can see there are eight children under variable state: ‘config’, ‘mock’, ‘states’, ‘wechat’, ‘user’, ‘car’, ‘order’, and ‘options’. Now I tell you that children like ‘config’, ‘mock’ and ‘options’ are all static data that won’t be changed through entire run-time. So it’s obviously that only children ‘states’, ‘wechat’, ‘user’, ‘car’, ‘order’. Absolutely, it’s not. The children ‘states’ is used to store data for common layout components like alert dialog popup, and you can see that there is method properties stored in children ‘state’, so it’s not appropriate to save it in localStorage. So finally, we only need to keep data in ‘wechat’, ‘user’, ‘car’ and ‘order’ persistent. So now you know why the configuration object passed to new VuexPersistence is as below:

const vuexLocal = new VuexPersistence({
  storage: window.localStorage,
  reducer: state => ({
    user: state.user,
    wechat: state.wechat,
    car: state.car,
    order: state.order
  }),
  filter: (mutation) => (
    mutation.type === 'setUser' ||
    mutation.type === 'setWechat' ||
    mutation.type === 'setCar' ||
    mutation.type === 'setOrder' ||
    mutation.type === 'resetAllStoreInfo'
  )
})
const vuexLocal = new VuexPersistence({
  storage: window.localStorage,
  reducer: state => ({
    user: state.user,
    wechat: state.wechat,
    car: state.car,
    order: state.order
  }),
  filter: (mutation) => (
    mutation.type === 'setUser' ||
    mutation.type === 'setWechat' ||
    mutation.type === 'setCar' ||
    mutation.type === 'setOrder' ||
    mutation.type === 'resetAllStoreInfo'
  )
})

I won’t cover configuration detail for vuex-persist, because you can simply open the official link here: https://www.npmjs.com/package/vuex-persist and read it online.

Conclusion
Actually, vuex-persist is just a nom package used to generate a vuex plugin which can save and restore data to and from api like localStorage. You can revise plugin alike yourself, if you read the source code of vuex-persist, you will know it’s just not a hard work. If you doesn’t know how to write a plugin for vuex, you can read this webpage: https://vuex.vuejs.org/en/plugins.html.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值