具有相同Vuex存储的多个Vue.js组件
在组件1中,有一些数据使用异步方法加载并存储在Vuex存储中。其他组件2正在使用同一存储,当用户从组件1导航到组件2时,必须清除数据 以下是正常的工作流程,工作正常具有相同Vuex存储的多个Vue.js组件,vue.js,vuex,Vue.js,Vuex,在组件1中,有一些数据使用异步方法加载并存储在Vuex存储中。其他组件2正在使用同一存储,当用户从组件1导航到组件2时,必须清除数据 以下是正常的工作流程,工作正常 组件1-加载数据完成(异步、等待) 用户导航到组件2 组件1数据在停用事件中被清除 组件2显示良好 现在,当用户打开组件1并快速导航到组件2时 组件1-数据请求已启动,但尚未加载数据 用户导航到组件2 组件1数据在停用事件中被清除 组件1异步操作已完成,数据现在已加载到状态 组件2将显示组件1的数据 当用户从组件1导航到组件2时,在
当用户从组件1导航到组件2时,在Vue生命周期中使用销毁的回调清除存储 A来源:
您仍然可以添加一个状态来检查用户当前的导航页面,并在存储区中设置一个标志,以更新状态“仅用户在预期组件中”,否则只需忽略当用户从组件1导航到组件2时,使用Vue生命周期中的已销毁回调清除存储区 A来源:
您仍然可以添加一个状态来检查用户当前的导航页面,并在存储区中设置一个标志,以更新状态“仅用户在预期组件中”,否则请忽略我仍然认为您应该重新构造组件,使其在视图组件而不是存储区中加载数据。存储区用于在不同视图之间共享的数据,或至少与应用程序的更广泛部分相关的数据,而您的数据似乎只特定于一个视图。只需通过道具传递数据即可
Views
- View A
- View B
Components
Common
- Sidebar (the common sidebar that is loaded in both View A and View B)
- Some other components specific to view a and b
如果您打算继续使用本地数据存储,我认为您有多种选择:
- 您可以使用url或视图名称为加载程序设置键。在您的状态中,您通常只会有数据,现在您有了一个将路由或视图名称映射到某些数据的对象。然后使用一个getter自动为您获取正确的数据。这样做的另一个好处是,如果愿意,您可以将数据保留在视图中,这样可以在返回到该视图时加快加载速度(不再需要进行api调用)
- 您向存储提交一些令牌,并且仅当令牌与检索令牌匹配时才覆盖存储状态中的数据。(例如,
之前执行dispatch('get/my/data',{token:'asdf'})
时。如果视图与我们当前所在的视图不匹配,我们只需丢弃数据即可commit('switch/to/view','asdf')
dispatch('get/my/data',{view:this.$options.name})
(或:this.$route.path
或this.$route.name
)的内容来分派加载操作
如果使用组件名称,则必须按照上述方式进行提交。否则,只需使用“../router”导入路由器或类似的方式导入路由器即可
对于第一个选项,您可以得到如下内容:
从“../router”导入路由器;
从“Vue”导入Vue
{
state: {
data: {},
},
getters: {
getData (state) {
return state.data[router.currentRoute.path];
}
},
mutations: {
setData (state, { view, data }) {
Vue.$set(state.data, view, data);
}
},
actions: {
async fetchData ({ commit }, { view }) {
const data = await myApiPromise;
commit('setData', { view, data });
}
}
}
现在getData
如果您已加载该视图的数据,则返回数据;如果未加载,则返回undefined
。切换只需获取以前存储的数据,这可能对您有用,也可能对您有用
第二个选项与此类似,但您需要担心一个额外的变异。该变异是从每个视图中创建的调用的。销毁组件时不要担心自己清理,而是在执行提取之前进行清理
{
state: {
data: null,
view: '',
},
getters: {
getData (state) {
return state.data[router.currentRoute.path];
}
},
mutations: {
clearData (state) {
Vue.$set(state, 'data', null);
},
setData (state, { view, data }) {
if (state.view !== view) {
// Do not update
return;
}
Vue.$set(state, 'data', data);
},
setView (state, { view }) {
Vue.$set(state, 'view', view);
}
},
actions: {
async fetchData ({ commit }, { view }) {
commit('clearData');
const data = await myApiPromise;
commit('setData', { view, data });
}
}
}
我仍然认为您应该重新构造组件,使其将数据加载到视图组件中,而不是存储区中。存储区用于不同视图之间共享的数据,或至少与应用程序的更广泛部分相关的数据,而您的数据似乎只特定于一个视图。只需通过道具传递数据即可。
Views
- View A
- View B
Components
Common
- Sidebar (the common sidebar that is loaded in both View A and View B)
- Some other components specific to view a and b
如果您打算继续使用本地数据存储,我认为您有多种选择:
- 您可以使用url或视图名称为加载程序设置关键帧。在您的状态下,您通常只需要数据,现在您有了一个将路由或视图名称映射到某些数据的对象。然后,您可以使用getter自动为您获取正确的数据。这样做的附加好处是,如果愿意,您可以将数据保留在其中当您返回到该视图时,可以加快加载速度(不再需要执行api调用)
- 您向存储提交一些令牌,并且仅当令牌与检索令牌匹配时才覆盖存储状态中的数据。(例如,
dispatch('get/my/data',{token:'asdf'})
而之前执行commit('switch/to/view','asdf'))
。如果视图与我们当前所在的视图不匹配,我们只需丢弃数据即可
在这两种情况下,您都会使用类似于dispatch('get/my/data',{view:this.$options.name})
(或:this.$route.path
或this.$route.name
)的内容来分派加载操作
如果使用组件名称,则必须按照上述方式进行提交。否则,只需使用“../router”
导入路由器或类似的方式导入路由器即可
对于第一个选项,您可以得到如下内容:
从“../router”导入路由器;
从“Vue”导入Vue
{
state: {
data: {},
},
getters: {
getData (state) {
return state.data[router.currentRoute.path];
}
},
mutations: {
setData (state, { view, data }) {
Vue.$set(state.data, view, data);
}
},
actions: {
async fetchData ({ commit }, { view }) {
const data = await myApiPromise;
commit('setData', { view, data });
}
}
}
现在getData
如果您已加载该视图的数据,则返回数据;如果未加载,则返回undefined
。切换只需获取以前存储的数据,这可能对您有用,也可能对您有用
第二个选项是类似的,但您有一个额外的变种