首页 > 解决方案 > 从持久存储重新水化后,Vuex getter 不会更新

问题描述

我的 Electron + Vue 设置遇到了一个奇怪的问题。

条件: Electron + Vue(我使用了样板文件)+ vuex-persist(也尝试了 vuex-persistedstatevuex-persistfile)。

问题: Vuex getter 在 store 被补水时保持 0/null/''。我怎么知道?如果本地存储是干净的(我第一次启动应用程序),第一个突变更新状态(getter 返回正确的值),我可以看到一个对象被添加到浏览器的本地存储中。但是,当应用程序重新启动时,突变会像以前一样触发状态和本地存储更新,getter 保持为空/默认。下面的 getter 返回一个空数组。

在此处输入图像描述

设置:我有一个与 3rd 方 API 配合使用的应用程序:获取数据、计算内容并将一些数据发回。API 也需要授权。下面是我的 Vuex 结构。

我的状态对象的一部分...

const state = {
  token: '',
  projects: [],
  work_packages: [],
  timeEntriesLocal: []
}

...和我的一个吸气剂:

const getters = {
  todayLog () {
    function sameDay (d1, d2) {
      return d1.getFullYear() === d2.getFullYear() &&
        d1.getMonth() === d2.getMonth() &&
        d1.getDate() === d2.getDate()
    }
    var entries = state.timeEntriesLocal
    var todayEntries = []
    entries.forEach(element => {
      var date = element.spentOn
      var today = new Date()
      if (sameDay(date, today)) {
        todayEntries.push(element)
      }
    })
    return todayEntries
  }
}

它从数组中返回由于“今天”而产生的条目。

timeEntriesLocal 填充了这个方法:

addTimeEntry () {
  let entry = {
    id: this.$store.state.UserData.timeEntriesLocal.length + 1,
    project: this.getItemById(this.$store.state.UserData.current.project_id, this.$store.state.UserData.projects),
    spentOn: new Date(),
    comment: this.comment,
    activityId: this.activityId,
    workPackage: this.getItemById(this.$store.state.UserData.current.work_package_id, this.$store.state.UserData.work_packages),
    hours: this.precisionRound(this.$store.state.UserData.duration / 60 / 60, 2),
    published: false,
    loading: false,
    infoMessage: ''
  }

  this.$store.commit('ADD_LOCAL_ENTRY', entry)
}

最后是我刚刚在上面使用的突变:

ADD_LOCAL_ENTRY (state, entry) {
  state.timeEntriesLocal.unshift(entry)
}

标签: javascriptvuejs2local-storageelectronvuex

解决方案


由于您正在更改timeEntriesLocalArray 的长度,因此未获取更改。这是文档的Common Gotchas部分中涵盖的 JavaScript 限制。Vuex 的文档中还介绍了一种解决方法:

突变遵循 Vue 的反应规则

由于 Vuex 存储的状态是由 Vue 做出的反应,所以当我们改变状态时,观察状态的 Vue 组件会自动更新。这也意味着 Vuex 突变在使用普通 Vue 时会受到相同的反应性警告:

  1. 更喜欢预先使用所有所需字段初始化商店的初始状态。
  2. 向对象添加新属性时,您应该:

    • Use Vue.set(obj, 'newProp', 123), 或者
    • 用一个新的对象替换那个对象。例如,使用对象扩展语法,我们可以这样写:state.obj = { ...state.obj, newProp: 123 }

因此,在您的示例中,要让 Vue (Vuex) 检测到这些更改,您可以执行以下操作:

ADD_LOCAL_ENTRY (state, entry) {
    state.timeEntriesLocal.unshift(entry);
    Vue.set(state, 'timeEntriesLocal', state.timeEntriesLocal);
}

推荐阅读