3

Vue中刷新当前页的几种方式及优劣分析

 2 years ago
source link: https://hooray.github.io/posts/de7170ad/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Vue中刷新当前页的几种方式及优劣分析

发表于

2019-12-17 更新于 2019-12-19 分类于 Vue 相关

阅读次数:

本文字数: 2.5k 阅读时长 ≈ 2 分钟

这个问题其实百度一下就有一堆解决方案,但是却很少有文章去分析他们各自的优势和劣势,而我这篇文章,也是在具体项目开发中,踩过一些坑后的心得和总结。

基本不会使用的方案,就是通过 location.reload() 或者 $router.go(0) 进行一次页面重新载入,效果等同于手动按 F5 刷新。

为什么说基本不用,因为弊端也很明显。首先体验不好,页面重新载入会出现大段时间的白屏;其次如果使用了 Vuex ,刷新可能会导致数据被清空。

准备一个空白页,页面里只做一件事,就是 $router.go(-1) ,需要刷新当前页的时候,只需跳转到该页面即可。

这个方案也会出现一小段白屏的时间,但问题不大,可以通过一些 loading 效果遮盖;其次因为是前进到一个空白页,再返回当前页,在 PC 端会出现一个小的 bug ,就是刷新一次之后,浏览器上的前进按钮会变成可点击,演示如下图:

网上能搜到最推荐的解决方案。就是通过 v-if 控制 <router-view> 的显示,如果要刷新页面,则将 <router-view> 销毁再重建一次即可。具体实现代码如下:

主要改造的就是 App.vue 文件

<template>
<div id="app">
<RouterView v-if="isRouterAlive" />
</div>
</template>

<script>
export default {
provide() {
return {
reload: this.reload
}
},
data() {
return {
isRouterAlive: true
}
},
methods: {
reload() {
this.isRouterAlive = false
this.$nextTick(() => (this.isRouterAlive = true))
}
}
}
</script>

通过 Vue 的 provide / inject ,将 App.vue 里的 reload() 方法注入到子页面里,这样在子页面里就可以通过这样的方式使用了。

<script>
export default {
inject: ['reload'],
methods: {
func() {
this.reload()
}
}
}
</script>

当然还可以更极致一点,就是直接在 App.vue 里监听路由的变化,如果当前路由和上一个路由的 name 属性一样,则可以认为是刷新页面操作,自动执行 reload() 方法。实现代码如下:

<template>
<div id="app">
<RouterView v-if="isRouterAlive" />
</div>
</template>

<script>
export default {
provide() {
return {
reload: this.reload
}
},
data() {
return {
isRouterAlive: true
}
},
watch: {
$route: 'routeChange'
},
methods: {
reload() {
this.isRouterAlive = false
this.$nextTick(() => (this.isRouterAlive = true))
},
routeChange(newVal, oldVal) {
if (newVal.name == oldVal.name) {
this.reload()
}
}
}
}
</script>

这样的好处在于,如果是在同一个路由,但不同参数间的跳转,能实现自动刷新页面。例如商城系统里最常见的,从一个商品详情页跳转到另一个商品详情页,这个时候,路由其实是没变化的,变化的只是 params 或者 query ,就不需要手动再去执行注入的 reload() 方法了。

这个方案看起来很完美,但有没有弊端呢?其实是有的,就是当项目在使用 keep-alive 做页面缓存的时候,会出现明显的问题。

因为一般做页面缓存都是通过 keep-alive 将 <router-view> 进行整页缓存,而刷新页面则是将 <router-view> 销毁并重建,所以一刷新,缓存就一并销毁了,所以在一些比较特殊的场景,还是有问题存在。

在遇到这样需要缓存页面的场景,方案二就体现出它的优势了。因为它是通过路由跳转刷新当前页面的,所以 <router-view> 始终都存在,就也能保证 keep-alive 的页面缓存不受到任何影响。

这种属于不太通用处理办法,就是在当前页面里手动再次获取相关数据,覆盖原有数据,实现刷新。这个方案的好处就是自由度更高,想重新获取哪些数据,就获取哪些数据,当然开发效率也会变低,因为无法形成通用的方案,到底要刷新哪部分数据,每个页面的业务逻辑都不一样。

说白了,其实没有一种方案是完美的,还是得根据不同的场景,选择适合的解决方案。当然我个人还是更喜欢方案二和方案三结合使用,因为页面缓存使用的场景也是挺多的。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK