我们在我们的应用程序中使用持久化的本地存储状态。
向商店模块添加新字段或值时,它们不会应用于现有用户的状态。它仅在清除存储时有效。
应该如何解决这个问题?
我想到的一个可能的解决方案如下:
这是一个可行的选择还是有更好的方法来处理这个问题?
在不深入了解实现细节的情况下,您应该像这样将 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 会在提交到它的内部状态后相应地更新状态。