本文章存在缺陷,最後也沒可以完善這個方案,你們看看就好。不過用這位大牛寫的項目能夠解決問題,配置也特別簡單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
界面切換和不一樣層級界面的切換示例。