vue点击当前路由刷新
背景
这里的当前路由刷新当然不是简单的当前页面的刷新。如果使用
- ❌
location.reload()
- ❌
this.$router.go(0)
其实最终效果都是刷新了当前浏览器页面,就像你手动F5
的效果,这当然不是我们想要的效果,会有闪屏,用户体验不够友好(你试试就知道了)。我们想要的效果应该是下图所示的亚子(就像在走前端路由那样):
实现方案
方案一:provide / inject
这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。虽然官方给出了下面的警告,但是只要不滥用,还是可以拿来解决实际问题的。
provide 和 inject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。
provide
选项是一个对象或返回一个对象的函数,该对象包含可注入其子孙的property。
inject
选项是一个字符串数组或对象(对象的key是本地的绑定名,value是注入的内容)
这里的实际问题我们如何通过这两组属性来实现呢?
首先在App.vue
文件中注入我们的provider
// App.vue
<template>
<div id="app">
<Layout class="full-height">
<TopMenu />
<Content class="framework-content">
<router-view v-if="isRouterAlive"></router-view>
</Content>
</Layout>
</div>
</template>
<script>
import TopMenu from '@/widget/TopMenu'
export default {
components: {
TopMenu
},
provide () {
return {
reloadRouter: this.reloadRouter
}
},
data () {
return {
isRouterAlive: true
}
},
methods: {
reloadRouter () {
this.isRouterAlive = false
this.$nextTick(() => this.isRouterAlive = true)
}
}
}
</script>
注意:我们的左菜单在router-view
内容中的
// 路由文件 router.js
{
path: '/xxx/xxx',
component: LeftMenu,
children: [{
path: 'home'
component: () => import('../xxx/xxx')
}]
},
// LeftMenu.vue
<template>
<Layout class="left-menu full-height">
<template v-if="leftMenuInfo">
<Sider>
<div class="title">
<Icon :type="leftMenuInfo.titleIcon" size="24" />
<span class="name">{{leftMenuInfo.titleText}}</span>
</div>
<Menu
ref="menuRef"
@on-select="handleSelect">
...
</Menu>
</Sider>
<Content class="sidebar-right">
<Breadcrumb v-if="breadcrum.length">
...
</Breadcrumb>
<div class="content">
<router-view></router-view>
</div>
</Content>
</template>
<template v-else>
<router-view></router-view>
</template>
</Layout>
</template>
<script>
export default {
inject: ['reloadRouter'],
data() {
return {}
},
methods: {
handleSelect(name) {
if (this.$route.path === name) {
// 如果当前点击的路由就是当前路由
this.reloadRouter()
} else {
this.$router.push(name)
}
}
}
}
</script>
方案二:空白页中转
// router.js
/* 空白页 */
{
path: '/refresh',
component: () => import('../pages/refresh')
},
// refresh.vue
<template>
</template>
<script>
export default {
beforeRouteEnter (to, from, next) {
next(vm => vm.$router.replace(from.path))
}
}
</script>
// LeftMenu.vue
handleSelect(name) {
if (this.$route.path === name) {
this.$router.replace('/refresh')
// this.reloadRouter() // provide/inject方案
} else {
this.$router.push(name)
}
}
原理其实就是当点击当前路由时,就跳转到空白页,在空白页对路由进行监控,当进入到空白页时就跳转到之前跳过来的页面去,以此实现实现当前页面的跳转。