从持久存储重新水化后,Vuex getter 不会更新

Posted

技术标签:

【中文标题】从持久存储重新水化后,Vuex getter 不会更新【英文标题】:Vuex getters are not updated after store re-hydration from persistent storage 【发布时间】:2019-05-15 18:47:14 【问题描述】:

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

条件: Electron + Vue(我使用了boilerplate)+ vuex-persist(也尝试了vuex-persistedstate 和vuex-persistfile)。

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

【问题讨论】:

【参考方案1】:

timeEntriesLocal 中的更改未被拾取,因为您正在更改数组的长度。这是文档的 Common Gotchas 部分中涵盖的 javascript 限制。 Vuex`s docs 中还介绍了一种绕过它的方法:

变异遵循 Vue 的反应规则

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

    最好使用所有需要的字段来初始化商店的初始状态 预付款。

    向对象添加新属性时,您应该:

    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);

【讨论】:

以上是关于从持久存储重新水化后,Vuex getter 不会更新的主要内容,如果未能解决你的问题,请参考以下文章

Vuex getter 不会更新

Firestore、vue、vuex、vuexfire:如何让 getter 真正从存储中获取数据?

vuex数据持久化

在使用 redux-persist 重新水化存储之前加载初始状态的默认值

Vuex - Getter

vuex使用前与使用后的写法---getters(获取事件)