vue實現前進刷新,後退不刷新

本文章存在缺陷,最後也沒可以完善這個方案,你們看看就好。不過用這位大牛寫的項目能夠解決問題,配置也特別簡單vue-navigaitionhtml

最近在用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置爲falseto路由的keepAlive置爲ture,就能在再次前進時,從新加載以前這個keepAlive被置爲false的路由了。github

廢話很少說了,這裏模擬有三個界面 loginservermainvue-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置爲falseto路由的keepAlive置爲turebash

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界面,我須要能從page3page4界面都能跳轉過去的話,那就須要爲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界面切換和不一樣層級界面的切換示例。

相關文章
相關標籤/搜索