需求描述
这几天开发,遇到一个很常见的需求:点击一个按钮,出现一个全局的表格;点击返回 或者菜单按钮,表格消失,回到初始页面。
代码实现
代码的实现也很简单,首先在store
中定义控制表格的显影状态listVisible
js
export const loopControlList = defineStore('loopControlList', {
state: (): State => {
return {
listVisible: false,
};
},
actions: {
setVisible(value: boolean) {
this.listVisible = value;
},
}
});
然后代码中引入,通过v-if控制显影
js
<template>
<div>
// 主应用
<MainBox v-show="!loopListStore.listVisible" />
// 表格组件
<LoopModuleList v-if="loopListStore.listVisible" />
</div>
</template>
<script setup>
import { loopControlList } from '@/store/loopControlList';
const loopListStore = loopControlList();
</script>
代码实现非常简单,相信大家没有任何问题。
有的人可能会杠,这么简单的问题为什么要使用pinia?注意,这里我只是把复杂的业务简单化了,抽象成了方便大家理解问题的简答代码场景
问题描述
我们的架构是基于qiankun框架 的,所有应用也都是通过子应用的方式接入框架的。当点击主应用的路由按钮时(下图照明按钮),会重新加载子应用的所有资源(network触发新的请求)。
但是,仔细看,当我点击【手动】按钮进入表格后,在点击主应用路由按钮【照明】后,就有问题了!
点击【照明】按钮,理论上子应用被重新加载,页面应该回到初始页面,但奇怪的是,居然直接进入了表格页面!
bug问题分析
出现这种问题,显然是一个bug,无非就是路由问题或者代码问题。很明显,路由的资源都被重新加载了,路由的问题概率不大,大概率是我们的代码问题。我们用了store进行了状态管理,先看一下store的值吧。
借助vue的调试工具,在没有打开表格页面前,store中的listVisible
值是false没有问题。
我们打开表格,store中的listVisible值是true也没有问题
但是,当我们点击主应用的路由按钮重新加载子应用时,意外出现了!store中的listVisible值居然没有变化!
这就奇怪了!子应用的所有资源都被重新加载
了,但是store中的值缺没有被初始化!居然还是页面注销前的状态值!
但如果我手动刷新页面,功能又会恢复正常!
看来bug的原因找到了:表格出现时,store中的listVisible值改成了true,当点击主应用的路由按钮时,虽然子应用被重载,但store中的listVisible值没变,导致点击路由时页面默认进入表格!
这么看来,store的状态值,会基于某种机制被浏览器缓存起来,除非强制刷新页面,否则这个状态值不会轻易改变!
如何解决
要规避这种问题,其实也非常简单,就是我们手动更改store中的值,比如在页面注销时,将值设为初始状态。
js
<template>
<div>
// 主应用
<MainBox v-show="!loopListStore.listVisible" />
// 表格组件
<LoopModuleList v-if="loopListStore.listVisible" />
</div>
</template>
<script setup>
import { loopControlList } from '@/store/loopControlList';
const loopListStore = loopControlList();
onBeforeUnmount(()=>{
loopListStore.setVisible(false)
})
</script>
这样做的话,就会完美解决问题
总结
在某些场景下,即使页面资源重新加载,store中的值也不会改变,而是维持着页面注销前的状态。因此,为了解决这个机制带来的可能异常,我们要养成良好的习惯,在页面注销时,进行store的销毁。
当然,至于为什么store的值在资源重载时没有改变,笔者也没有搞明白原理,希望各位大佬能答疑解惑!