Vue Router常用内容总结

0 阅读5分钟

Vue RouterVue官方的客户端路由解决方案。用于在单页应用中将浏览器的URL和用户看到的内容绑定起来。

使用Vue Router

通过createRouter创建路由器实例

可设置属性有:

  • linkActiveClass  链接激活时使用的CSS类名,默认使用router-link-active
  • linkExactActiveClass 链接被精确匹配时使用的CSS类名,默认使用router-link-exact-active
  • parseQuery & stringifyQuery  编译和解析查询的自定义实现,比如使用qs包对query参数执行 或对路由参数执行加解密操作
  • history  指定路由与URL路径是如何双向映射的
  • strict  为true时,将禁止尾部斜线
  • sensitive 为true时,将区分大小写
  • scrollBehavior 在页面之间导航时控制页面滚动,可返回promise设置延时滚动
  • routes 应该添加到路由器的初始路由列表

示例 router/index.ts

import {createMemoryHistory, createRouter} from 'vue-router'
const router = createRouter({
    linkActiveClass: 'router-link-active',
    linkExactActiveClass: 'router-link-exact-active',
    parseQuery: (search: string) => LocationQuery,
    stringifyQuery: (search: string) => LocationQuery
    // 指定路由与URL路径是如何双向映射的
    // createMemoryHistory() 会完全忽略浏览器的URL而使用自己内部的URL,其目的是为了处理服务端渲染
    // createWebHistory() URL不带#
    // createWebHashHistory() URL带#
    history: createWebHistory(),
    // 为true时,将禁止尾部斜线
    strict: true,
    // 为true时,将区分大小写
    sensitive: true,
    // 在页面之间导航时控制页面滚动
    scrollBehavior(to, from, savedPosition) {
      // 始终滚动到顶部
      return { top: 0 }
    },
    // 应该添加到路由器的初始路由列表
    routes: [
        {path: '/', component: HomeView}, // 把URL路径映射到组件
        ...
    ]
})

然后将路由实例挂载到应用实例上

main.ts

app.use(router)

使用路由后,要在根组件中使用RouterView渲染对应组件 一般在app.vue或者layout/default.vue中,如果是用vue-cli创建项目时自动引用的router,则生成代码中会自动改变,不需要手动修改

<template>
    <header>
           ...
    </header>

    <RouterView />
</template>

使用router之后会:

  • 全局注册RouterViewRouterLink组件
    • RouterView:可以根据URL路径渲染对应路由组件
    • RouterLink: 能够让Vue Router在不重新加载页面的情况下改变URL,处理URL的生成、编码和其他功能
  • 添加全局$router$route属性 (在组件模版和选项式API中使用)
    • $route:表示当前路由实例
    • $router:表示路由器实例
  • 启用useRouter()useRoute()组合式函数(在组合式API中使用)
    • 通过useRouter()可以获取路由器实例:const router = useRouter()
    • 通过useRoute()可以获取当前路由实例:const route = useRoute()
  • 触发路由器解析初始路由

路由匹配

默认情况下,所有路由是不区分大小写的,并且能匹配带有或不带有尾部斜线的路由

  • strict:配置strict: true时,将不会匹配带有尾部斜线的路由

  • sensitive:配置sensitive: true时,将区分大小写

    // router.ts
    const routes = [
        {
            // 匹配 /users、 /users/、 /Users/
            path: '/users',
            component: UserCom
        },
        {
            // 不匹配 /users/
            path: '/users',
            strict: true,
            component: UserCom
        },
        {
            // 不匹配 /users/
            path: '/users',
            sensitive: true,
            component: UserCom
        },
    ]
    

动态路由

  • 带参数的路由: router.ts

    const routes = [
      {
          // 匹配 比如 /detail/34
          path: '/detail/:id',
          component: DetailCom
      },
      {
          // ?表示可选参数,这里将id标记为可选, 匹配 /detail、 /detail/34
          path: '/detail/:id?,
          component: DetailCom
      },
    ]
    

    在组件DetailCom.vue中获取路由参数

    const route = useRoute();
    const id = route.params.id;
    
    // 响应路由参数的变化:
    // 当从/detail/1跳转到detail/2时,并不会触发组件的生命周期函数
    // 此时可以在组件中监听params触发相应逻辑
    watch(
        () => route.params.id,
        (newId, oldId) => {
            // 执行具体逻辑
        }
    )
    

嵌套路由

在一个路由中配置children数组,就是所谓的嵌套路由,相应的RouterView中也要嵌套RouterView

router.ts相关代码

const routes = [
  {
      path: '/user',
      component: UserLayout, // 用户管理的模版组件
      children: [
          {
               path: '',
               redirect: '/profile' // 访问/user路径将会重定向到 /user/profile
           },
           {
               // 匹配 /user/profile
               path: 'profile',
               component: UserProfile, // UserProfile组件将被渲染到UserLayout组件的<RouterView />内部
           }
      ]
  },
];

路由跳转

  • router.push

    const routes = [
      {
          path: '/user',
          name: 'user',
          component: UserLayout
      }
    ]
    
    // 以下三种方式是等价的
    router.push('/user')
    router.push({ path: '/user' })
    router.push({ name: 'user' })
    
  • router.replace

    // 用于替换history中当前路由
    router.replace({ path: '/home' })
    // 相当于
    router.push({ path: '/home', replace: true })
    
  • history中前进或后退

    // 向前移动一条记录,等同于router.forward()
    router.go(1)
    
    // 后退一条记录,等同于router.back()
    router.go(-1)
    
    // 参数可以是任意数字,如果匹配不到,则静默失败
    router.go(100)
    
  • 携带参数

    • params  

      // 携带params跳转, 显示在路径上为 /detail/34
      router.push({
          path: '/detail',
          params: { id: 34 }
      })
      // 等同于
      const id = 34;
      router.push({ path: `/detail/${id}` })
      
      // detail组件获取params参数
      const route = useRoute();
      const id = route.params.id;
      
    • query

      // 携带query跳转,显示在路径上为 /detail?type=typeValue
      router.push({
          path: '/detail',
          query: {
              type: 'typeValue'
          }
      })
      
      // detail组件获取query参数
      const route = useRoute()
      const type = route.query.type;
      
  • 路由组件传参

    • 可以通过设置props: true来配置路由将id` 参数作为 prop 传递给组件

      const routes = [
          { path: '/user/:id', component: User, props: true }
      ]
      
      // User组件
      const props = defineProps({
          id: String
      })
      console.log(props.id);
      

导航守卫

图片

钩子函数都接收tofrom入参,表示即将要进入的目标路由和正要离开的路由实例。

原来还会接受一个next入参,该入参已被移除,但仍可用

返回值可以是

  • false 表示取消当前的导航
  • 没有返回值(即undefined)或 true 表示钩子函数结束,继续当前路由跳转
  • 一个路由地址(比如 return '/login')表示路由重定向到指定路由
  • 如果意外抛出Error  会取消导航并触发router.onError()注册过的回调函数

KeepAlive & Transition

KeepAlive 组件可以保持路由组件活跃

默认情况下,<KeepAlive>将缓存其中的任何组件实例。我们可以通过 includeexclude 属性来自定义此行为。

其中设置的规则匹配的是组件name,所以需要为组件显式的指定name属性

<!-- comma-delimited string -->
<KeepAlive include="a,b">
    <component :is="view" />
</KeepAlive>

<!-- regex (use `v-bind`) -->
<KeepAlive :include="/a|b/">
    <component :is="view" />
</KeepAlive>

<!-- Array (use `v-bind`) -->
<KeepAlive :include="['a', 'b']">
    <component :is="view" />
</KeepAlive>

可以通过 max 属性缓存的组件实例的最大数量,如果缓存实例的数量即将超过指定的最大计数,则最近访问最少的缓存实例将被销毁,以便为新实例腾出空间。

当组件实例从 DOM 中删除,但它是 缓存的组件<KeepAlive>树的一部分时,它将进入停用状态,而不是被卸载。当组件实例作为缓存树的一部分插入到 DOM 中时,它将被激活

保持活动状态的组件可以使用 onActivated()onDeactivated() 为这两种状态注册生命周期钩子

Transtition 组件可实现路由组件间切换时实现过渡效果