💡简介
来自官网 https://router.vuejs.org/zh/guide/
Vue 让我们用组件组成了应用,而 Vue Router 又能将组件映射到路由上。
- router.js创建路由,同时将组件映射到路由上
- main.js引入- router.js,并- app.use(router)
- 在模板中使用,用到了两个组件 - <router-view>和- <router-link>
<nav>
    <!-- 使用 router-link 组件进行导航 -->
    <!-- 通过传递 `to` 来指定链接 -->
    <!-- `<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
    <router-link to="/">Go to Home</router-link>
    <router-link to="/about">Go to About</router-link>
</nav>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
1. 动态路由
在路径中使用一个动态字段(路径参数),路径参数用 : 表示,其值可通过 $route.params 来访问。比如:
- /users/:id
- /users/:username
- /users/:username/posts/:postId
1.1 参数变化时
当动态参数发生变化时,相同的组件实例会被重复利用(比起销毁再重建更高效),这就意味着组件的生命周期钩子不会被调用。
1.2 相应参数变化
此时如果要响应同一个组件中的参数变化,可以有以下办法:
- watch - this.$route对象的任意属性- Vue3 在 - setup里没有- this,所以是使用- useRouter,- useRoute函数
 
- 使用组件内导航守卫 - beforeRouteLeave,- beforeRouteUpdate- Vue3 用了组合式 API,所以是 - onBeforeRouteLeave,- onBeforeRouteUpdate组合式函数 API
 
- <router-view :key="$route.path">是强制刷新组件(先 destroy 再 re-render)
import { useRouter, useRoute, onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
const router = useRouter()
const route = useRoute()  // 避免监听整个 route 对象,应该直接监听期望改变的参数
// 在模板中可以访问 $router 和 $route2. 嵌套路由
要将组件渲染到嵌套的 router-view 中,就需要在路由中配置 children。
- 几个 - children就应该有几个- <RouterView />
- 空的嵌套路径,也很有用, - { path: '' }
- 通常会给路由命名,使用方便, - name属性
- 跳转,跳父路由 vs 跳子路由 
以 / 开头的嵌套路径将被视为根路径,这将允许我们利用组件嵌套,而不必使用嵌套的 URL。
3. 路由守卫
Navigation Guards
- 场景:普通路由、动态路由(对参数有效性的校验) 
- 用途:需要登录的页面、NotFoundPage,详见文末示例 
- 路由守卫的几种方式: - 全局 
- xxx 
 
4. 历史模式
History mode:HTML5 模式 vs Hash 模式
- HTML5 web history API,Single Page App 
- /#/home传统的 server side apps
5. 性能方面
5.1 懒加载(动态导入)
表现是最终打包的资源是否分包 ,写法是 dynamic import 路由的组件。
对应内容:bundle 源代码,每个 page 都有它自己的 chunk/file/bundle。
- Vite 的 code splitting 特性 - 开发模式下,Vite 没有 bundle 代码,直接用的浏览器原生的 import 
 
- Webpack 的 code splitting 特性 - 在 Vue 中可以用 magic comment 给每个组件对应的小 bundles 命名 
 
5.2 路由的草稿功能
切换路由时,保持草稿功能
<router-view v-slot="{ Component }">
    <keep-alive>
      <component :is="Component" />
    </keep-alive>
</router-view>6. 更多
6.1 更多特性
- 命名路由:没有硬编码的 URL、绕过路径排序 - <router-link :to="{name: 'user'}">
- router.push({name: 'user'})
 
- 路由的 - redirect和- alias。很实用的样子,详见下方示例
- 给路由传参: - props属性
- 路由的匹配语法 - 静态路由 
- 动态路由 
- 也可以使用正则表达式 - { path: '/xx/:id(\\d+)' }
 
- 动态增加路由,用脚本 add/remove 的 route record(比如某些插件) 
- 从整体配置哪些路由要特定组件(比如页面广告) - Named View, - <router-view name="xxx"></router-view>
- 路由配置用了 - components属性,而不是- component
 
- 路由组件切换时 - 动画:全局 Vue 组件 - <transition><transition>
- 滚动行为, - scrollBehavior属性
 
<!-- Vue2 动画 -->
<transition>
    <router-view></router-view>
<transition>
<!-- Vue3 动画 -->
<router-view v-slot="{Component}">
    <!-- name 指定 css 的类名,  slide | moveUp | fade,  back-in -->
    <transition name="slide" mode="out-in"> 
        <component :is="Component"></component>
    </transition>
</router-view>
6.2 注意事项
- <RouterLink>vs- <a>- 前者只刷新路由组件,它会拦截 click 事件。适合内部链接 
- 后者会 reload 整个页面,适合外部链接 
 
- 当前选中的路由,有类名 - .router-link-acitive,也可以用- linkActiveClass自定义
- 路由跳转 - 在模板里用 - <router-link>
- 在脚本里用 - $router.push,- $router.replace。不同之处是如何影响路由历史
 
- route的- fullPath和- path- fullPath包括 path, query, hash
- path包括 path
 
- components文件夹放整个 App 的组件,若是某个 page 的则放自己- views/page/components
- 监测路由失败 - import { isNavigationFailure, NavigationFailureType } from 'vue-router'失败的原因可能如下图

7. 示例
const routes = [
  {
    path: '/',
    component: () => import('@/views/HomeView.vue'),
    children: [
      {
        path: '',
        alias: ['/home', '/search'],
        name: 'ResultList',
        component: () => import('@/views/home/ResultListView.vue')
      },
      {
        path: 'preview/:id',
        name: 'CardPreview',
        component: () => import('@/views/home/CardPreview.vue')
      },
      {
        path: 'feature/:cat',
        name: 'FeatureList',
        component: () => import('@/views/home/FeatureView.vue'),
        beforeEnter: (to, from) => {
          const cat = to.params.cat
          if (cat === 'html' || cat === 'css') {
          } else {
            return { name: 'NotFound' }
          }
        }
      }
    ]
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/LoginView.vue')
  },
  {
    path: '/admin',
    component: () => import('@/views/AdminView.vue'),
    meta: {
      requiresAuth: true
    },
    children: [
      {
        path: '',
        name: 'AdminList',
        component: () => import('@/views/admin/ListView.vue')
      },
      {
        path: 'card',
        name: 'AdminCard',
        component: () => import('@/views/admin/CardView.vue')
      }
    ]
  },
  {
    path: '/:pathMatch(.*)*',
    name: 'NotFound',
    component: () => import('@/views/NotFound.vue')
  }
]
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes
})
方法
- install()
- isReady()
- onError()错误处理程序
- back: () => go(-1)
- forward: () => go(1)
- go()
- push()
- replace()
- beforeResolve()导航守卫
- beforeEach()导航守卫
- afterEach()导航钩子
- getRoutes()路由记录的完整列表
- hasRoute()
- resolve()返回路由地址的标准化版本
- addRoute()动态添加/删除路由
- removeRoute()
属性
- currentRoute
- options
- listening
- __hasDevtools
最重要的是了解原理,因为具体的写法和某些约定可能会变(知识本身在更新)。
- 深入的:原理、实现 
- 宽泛的:有几种方式,它们的适用场景和特点 
有关路由的详细参数,详见 Vue Router API 参考。
Last updated