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界面切换和不一样层级界面的切换示例。

相关文章
相关标签/搜索