javascript 如何引入对Vuex持久化状态的更改?

5lhxktic  于 2023-03-11  发布在  Java
关注(0)|答案(1)|浏览(102)

bounty将在4天后过期。回答此问题可获得+50声望奖励。kuntervert希望引起更多人关注此问题。

我们在应用程序中使用持久化本地存储状态。
当向存储模块添加新字段或值时,它们不会应用于现有用户的状态。它只在清除存储时才起作用。
我们应该怎样着手解决这个问题呢?
我想到的一个可能的解决方案如下:
1.创建一个prototype/helper对象,用于状态初始化
1.加载应用程序时,获取用户的状态对象,并将键/值对与原始对象进行比较
1.查找丢失的数据并将其添加到用户的状态对象中
这是一个可行的选择,还是有更好的办法来处理这个问题?

pw9qyyiw

pw9qyyiw1#

无需深入了解实现细节,您应该将localStorage状态与现有的vuex状态合并,如下所示:

export const mutations: MutationTree<YourState> = {
   MERGE_USER_STATE(state, userState: Partial<YourState>) {
      state = {...state, ...userState};
   }
}

这将使用缓存在用户localStorage中的以前状态扩展现有状态。现有键将被覆盖,而新键将被保留。
但这也有一些缺点:

  • 嵌套的对象总是被覆盖。因此对象内部的新键被覆盖
  • 您无法跟踪每个用户状态中存储的内容,这可能会使调试变得相当复杂。

一个更好的方法是使用版本控制机制并自己处理转换,这样你就知道了存储在用户本地存储中的模式,并可以将该模式转换成任何你想要的模式。
假设用户具有包含以下内容的本地存储state项:

{ 
  version: 1, 
  data: {
     favoriteAnimals: ["Dog", "Cat"]
  }
}

假设有一个VUEX商店允许用户添加/编辑他们最喜欢的动物:

export const state = () => {
  version: 1,
  favoriteAnimals: []
}

export const mutations = {
   ADD_ANIMAL(state, animal: string){
     state.favoriteAnimals.push(animal);
     localStorage.setItem('state', JSON.stringify({
      version: state.version,
      data: state
   })
)

   },
   // more mutations to remove and whatnot
}

export const actions = {
   add(context, animal: string){
      commit("ADD_ANIMAL", animal);
   },

   load(context, userState: string){ // userState = localStorage state
      const {version, data} = JSON.parse(state);
      // for now we don't care about data. we assume data is an array of strings
     data.forEach(animal => commit("ADD_ANIMAL", animal);
   }
}

现在,你的团队几周后决定将最喜欢的动物列表从字符串列表改为对象列表,如下所示:

[ { animal: "Dog", ranking: 5 } ]

显然,当用户使用旧的本地存储访问时,您的应用程序将中断,因为类型现在不兼容。
现在您可以编辑load操作,如下所示:

load(context, userState: string){ // userState = localStorage state
     const {version, data} = JSON.parse(state);
     if (version === 1){ // old user detected.
        data.forEach(animal => {
            commit("ADD_ANIMAL", { name: animal, ranking: 0 });
        });
        return;
     }
     
     // default action when the version is up to date
     data.forEach(animal => commit("ADD_ANIMAL", animal);
}

在一定的规模下,这个功能会变得越来越强大,不过我认为它很好,因为它很容易扩展。你可以随时添加分析功能,跟踪你的用户实际使用的是哪个版本。这还有一个额外的好处,即每个用户打开应用程序时,其状态都会自动更新,因为vuex在提交到其内部状态后会相应地更新状态。

相关问题