VueRouter 后退页面刷新问题解决方案
用 VueRouter hash 模式时,点击浏览器上的后退按钮,浏览器显示上一次浏览页面的时候,会重新执行页面,像页面刷新一样。
跟微信小程序不一样,微信小程序后退的时候不会重新执行,只是给我们一个
onShow
事件,这样如果需要刷新数据,我们就可以在onShow
里面解决。
解决方案1:用 keep-alive
组件
使用 Vue 内置的 keep-alive 组件。
使用该组件后,可缓存组件状态, 页面二次显示时,触发 onActivated
事件,我们可在 onActivated
中决定是否刷新列表数据。
此方法解决比较完美,但是稍微复杂,并发性能要求较高时,推荐使用该方案。
第1步,修改 router-view 标签
把 <router-view></router-view>
改为:
1 | <router-view v-slot="{ Component, route }"> |
用
keep-alive
需要注意的是:组件第一次打开加载数据渲染页面,第二次打开时,不管你是点击链接还是前进后退到该组件,都是触发onActivated
、onDeactivated
事件,而不会重新执行&渲染页面,因此需要手动检测数据更新时重新加载数据。
第2步,路由设置
在需要保持状态的页面的路由上加上 meta.keepAlive = true 参数,如
1 | { path: '/orders', component: () => import('./pages/order/Index.vue'), meta: { keepAlive: true } } |
第3步,数据有更新则刷新列表数据
详情页更改后,标记数据已更改,然后再在列表页检测数据是否变更,变更则刷新数据。
1 | <!-- pages/order/Index.vue --> |
解决方案2:把请求参数同步到 hash 后的查询参数
并发要求不高的可用此方法,简单。
修改 hash 的查询串,页面不会被刷新。如果列表页有请求参数变化时,可修改 URL hash,把请求参数替换到 hash 后面的查询串,页面加载时根据请求参数请求服务器数据。这样就完全不用检查列表数据是否已更新,还能保证数据实时性,唯一美中不足的是,后退还要重新请求服务器数据、重新渲染页面。
1 | axios.get('/admin/users', query, (resp) => { |
解决方案3:把子页面封装成模态窗子组件
列表页的新建、编辑、查看详情可做成 模态窗 方式,不存在后退到列表页的情况,自然就不用担心页面重新执行的问题,而且用户体验还更好。
如果表单页面比较复杂,再使用前面的方案。
注意:数据更新后注意刷新列表数据。新建、编辑后都需要刷新列表数据,因此建议在父组件(列表页)暴露刷新数据的方法,再在新建、编辑组件中回调。
实现1 使用 expose
在子组件的 setup
中用 getCurrentInstance().parent.exposed
可以访问父组件用 defineExpose
暴露的绑定。
编辑用户组件(页面):
1 | <!-- user/Edit.vue --> |
列表组件(父),引用编辑用户信息组件(子)
1 | <!-- user/Index.vue --> |
实现2:使用依赖注入
方案3的实现方案也可以用
依赖注入
实现,在父组件使用provide
提供依赖,在子组件用inject
注入上层组件提供的数据或方法。
在
setup
中访问父组件,使用依赖注入更便捷。在模板中访问上层组件,用 expose 更方便
1 | <script setup> |
1 | <!-- 父组件 --> |
VueRouter 后退页面刷新问题解决方案
https://coderpan.com/front-end/vuerouter-refresh-on-back-solution.html