最近在用keep-alive配合vuex做缓存处理。发现在某些场景下,keep-alive设置的include不会立即生效,但是include的值确实已经改变。
具体的原因如下。在router.beforeEach中dispatch关于keep-alive的action,在action中根据路由对state中的include动态增删。然后在相应的页面组件中mapState获取该include。我发现路由的跳转优先于mapState获取include,导致缓存不会立即生效。由此可见mapState获取值应该是异步的。
解决办法,在action中使用promise包装,在router.beforeEach使用await或者.then实现同步,保证include修改完成并mapState到组件中,再进行路由的跳转。
出现该问题的场景如下图:
点切换左侧导航时,清空store中的include,重新点击下钻并动态修改include。此时,返回上一页面会重新发起网络请求,缓存失效!
我发现生命周期即进入了created,也进入了activated。也就是说state中include的修改晚于router的跳转。怀疑在router.beforeEach拦截处理include时,出现了异步,导致路由优先进入然后组件才通过mapState获取到新的include的值。
于是,我将action中操作include的函数使用primise封装起来,如下:
const actions = {
changeKeepAlive({ commit }, { to, from }) {
return new Promise((resolve, reject) => {
if (!to.path.includes('/home/menu')) { // 不是首页, 清空keepalive
commit('CLEAR_INCLUDE');
resolve();
} else {
let fromIsInKeepAlive = state.include.includes(from.name);
if (to.meta.index < from.meta.index && fromIsInKeepAlive) { // 后退时,若当前页被缓存,移除缓存配置
commit('DELETE_INCLUDE', from.name);
resolve();
}
if (to.meta.index > from.meta.index && !fromIsInKeepAlive) { // 前进时,下一页需要缓存,添加该页面
commit('ADD_INCLUDE', from.name);
resolve();
}
}
resolve();
});
}
};
然后在main.js中的router.beforeEach中(也可以使用await):
store.dispatch('keepAlive/changeKeepAlive', {to, from}).then(() => {
...
})
再次尝试,发现缓存已经正常。初步估计mapState是异步的,双向绑定的值能够及时的更新,但是keep-alive的include需要在路由跳转前修改。