本文章存在缺陷,最后也没可以完善这个方案,你们看看就好。不过用这位大牛写的项目能够解决问题,配置也特别简单vue-navigaition。html
最近在用vue尝试着作移动端的项目。但愿实现前进刷新、后退不刷新的效果。即加载过的界面能缓存起来(返回不用从新加载),关闭的界面能被销毁掉(再进入时从新加载)。例如对a->b->c 前进(b,c)刷新,c->b->a 后退(b,a)不刷新。vue
因为keep-alive
会把全部加载过的界面都缓存起来,无法实现返回时将界面销毁掉,致使再进入时没有从新加载这个界面。因而首先想到的方案是在点击界面上返回按钮的时候,调用this.$destroy(true)
来将界面销毁掉。可是在移动端 android设备上会有物理返回键,若是经过物理返回键返回的话,就无法处理了。虽然能够重写android的返回事件,来调用js的方法,可是调用的是js的全局方法,无法具体让在最上层的那个界面销毁掉。android
因而就须要另辟蹊径了。还好这篇文章给了我启发vue-router 之 keep-alive,多谢做者的分享。git
要是可以知道路由是前进仍是后退就行了,这样的话我就能在后退的时候让from
路由的keepAlive
置为false
,to
路由的keepAlive
置为ture
,就能在再次前进时,从新加载以前这个keepAlive
被置为false
的路由了。github
废话很少说了,这里模拟有三个界面 login
到server
到main
。vue-router
首先我给这三个界面路由的path
设置了严格的层级关系 ,并设置keepAlive
都是true
,默认都是须要缓存。缓存
const router = new Router({
routes: [
{
path: '/',
redirect: '/login'
},
{
path: '/login',
component: Login,
meta: {
keepAlive: true
}
},
{
path: '/login/server',
component: ServerList,
meta: {
keepAlive: true
}
},
{
path: '/login/server/main',
component: Main,
meta: {
keepAlive: true
}
}
]
})
复制代码
因为这三个界面path的层级不一样,我就能经过beforeEach
这个钩子判断出何时是后退了。在后退时将from
路由的keepAlive
置为false
,to
路由的keepAlive
置为ture
。bash
router.beforeEach((to, from, next) => {
const toDepth = to.path.split('/').length
const fromDepth = from.path.split('/').length
if (toDepth < fromDepth) {
console.log('后退。。。')
from.meta.keepAlive = false
to.meta.keepAlive = true
}
next()
})
复制代码
最后须要缓存的界面用keep-alive
包起来,就能实现时前进刷新,后退时不刷新的效果了。ui
<keep-alive>
<router-view v-if="$route.meta.keepAlive">
<!-- 这里是会被缓存的视图组件 -->
</router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive">
<!-- 这里是不被缓存的视图组件 -->
</router-view>
复制代码
补充说明this
这个方法确实很取巧,像lyh2668
所说的单纯从length
判断会有不少场景有问题。好比 有一个page5
界面,我须要能从page3
和page4
界面都能跳转过去的话,那就须要为page5
配置两个路由path
了,假设page
几的path
层级就是几的话,那么就要为page5
配置层级4和层级5的两个路由路径了(固然直接就配置一个路由层级5的话也是可行的,只须要保证比跳转到它的界面的层级都大就能够)。
另外能够像lyh2668
所说的把keepAlive
换成noKeepAlive
,这样的话就不用在每一个router
中去配置keepAlive
了,就方便了不少。关于层级也能够不经过/
来判断,好比在path
末尾加数字等其它方式来实现。
另外lyh2668
所说的压栈的方式,我也有搜到过,可是在有tab
界面的时候这种方式就不适合了,由于tab
界面切换的时候不须要这种效果,但也会被压栈。可是用个人方法的话,就能够把tab
界面的路由都设置为同一个层级,就不会有问题了
这是是压栈方式的代码,在没有tab界面的时候,这种方式确实会更好用。
let routerList = []
router.beforeEach((to, from, next) => {
if (routerList.length && routerList.indexOf(to.name) === routerList.length - 1) {
// 后退
routerList.splice(routerList.length - 1, 1)
to.meta.isBack = true
} else {
// 前进
routerList.push(from.name || '/')
to.meta.isBack = false
}
next()
})
复制代码
欢迎有更好方法的朋友可以指点分享。
已添加Demo
说明,见github。包括普通界面切换、tab
界面切换和不一样层级界面的切换示例。