0
点赞
收藏
分享

微信扫一扫

vue 中路由的使用

定义路由的时候可以配置 meta 字段:

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      children: [
        {
          path: 'bar',
          component: Bar,
          // a meta field
          meta: { requiresAuth: true }
        }
      ]
    }
  ]
})

首先,我们称呼 routes 配置中的每个路由对象为 路由记录。路由记录可以是嵌套的,因此,当一个路由匹配成功后,他可能匹配多个路由记录。

例如,根据上面的路由配置,/foo/bar 这个 URL 将会匹配父路由记录以及子路由记录。

一个路由匹配到的所有路由记录会暴露为 $route 对象(还有在导航守卫中的路由对象)的 $route.matched 数组。因此,我们需要遍历 $route.matched 来检查路由记录中的 meta 字段。

下面例子展示在全局导航守卫中检查元字段:

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    // this route requires auth, check if logged in
    // if not, redirect to login page.
    if (!auth.loggedIn()) {
      next({
        path: '/login',
        query: { redirect: to.fullPath }
      })
    } else {
      next()
    }
  } else {
    next() // 确保一定要调用 next()
  }
})

router-view是基本的动态组件,所以我们可以用transition组件给它添加一些过渡效果:

<transition>
  <router-view></router-view>
</transition>

Transition 的所有功能 在这里同样适用。

1. 单个路由的过渡

上面的用法会给所有路由设置一样的过渡效果,如果你想让每个路由组件有各自的过渡效果,可以在各路由组件内使用 并设置不同的 name。

const Foo = {
  template: `
    <transition name="slide">
      <div class="foo">...</div>
    </transition>
  `
}

const Bar = {
  template: `
    <transition name="fade">
      <div class="bar">...</div>
    </transition>
  `
}

2. 基于路由的动态过渡

还可以基于当前路由与目标路由的变化关系,动态设置过渡效果:

<!-- 使用动态的 transition name -->
<transition :name="transitionName">
  <router-view></router-view>
</transition>

接着在父组件内 watch 监听 $route 决定使用哪种过渡:

watch: {
  '$route' (to, from) {
    const toDepth = to.path.split('/').length
    const fromDepth = from.path.split('/').length
    this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
  }
}

在开发中,我们遇到这样的一个常见的的场景,从主页 跳转到 列表页 跳转到 详情页,详情页 返回 列表页 返回 首页。我们希望,从 详情页 返回 列表页 的时候页面的状态是缓存,不用重新请求数据,提升用户体验。从 列表页 返回 主页 的时候页面,注销掉列表页,以在进入不同的列表页的时候,获取最新的数据。

上述的按需加载的场景可以使用之前提到过的keep-alive标签实现:

keep-alive接收三个参数:

  • include:可传字符串、正则表达式、数组,名称匹配成功的组件(组件名称)会被缓存
  • exclude:可传字符串、正则表达式、数组,名称匹配成功的组件不会被缓存
  • max:可传数字,限制缓存组件的最大数量

includeexclude,传数组情况居多

直接将路由占位符放进去就行了

<keep-alive :include="allowList" :exclude="noAllowList" :max="amount">
    <router-view></router-view>
</keep-alive>

动态路由实现

(1)在Router里定义好需要缓存的视图组件

new Router({
    routes: [
        {
            path: '/',
            name: 'index',
            component: () => import('./views/keep-alive/index.vue'),
            meta: {
                deepth: 0.5
            }
        },
        {
            path: '/list',
            name: 'list',
            component: () => import('./views/keep-alive/list.vue'),
            meta: {
                deepth: 1
                keepAlive: true //需要被缓存
            }
        },
        {
            path: '/detail',
            name: 'detail',
            component: () => import('./views/keep-alive/detail.vue'),
            meta: {
                deepth: 2
            }
        }
    ]
})

(2)写2个router-view出口

<keep-alive :include="include">
    <!-- 需要缓存的视图组件 -->
  <router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>

<!-- 不需要缓存的视图组件 -->
<router-view v-if="!$route.meta.keepAlive"></router-view>

(3)在 app.vue 里监听路由的变化

export default {
  name: "app",
  data: () => ({
    include: []
  }),
  watch: {
    $route(to, from) {
      //如果 要 to(进入) 的页面是需要 keepAlive 缓存的,把 name push 进 include数组
      if (to.meta.keepAlive) {
        !this.include.includes(to.name) && this.include.push(to.name);
      }
      //如果 要 form(离开) 的页面是 keepAlive缓存的,
      //再根据 deepth 来判断是前进还是后退
      //如果是后退
      if (from.meta.keepAlive && to.meta.deepth < from.meta.deepth) {
        var index = this.include.indexOf(from.name);
        index !== -1 && this.include.splice(index, 1);
      }
    }
  }
};

代码中的 push 和 splice 的是 router 的 name。建议把 route 的 name属性设置和 route对应componentname设成一样的。

举报

相关推荐

0 条评论