Vue Router 是 Vue 官方为“单页应用”量身定制的导航管家。它把 URL 当成地图坐标,把组件当成房间,只需在地址栏输入路径,就能瞬间“瞬移”到对应房间,无需整页刷新。最新 v4 版本全面拥抱 Vue3:API 组合式、TypeScript 类型完备;路由懒加载粒度更细,首屏加载速度肉眼可见地提升;嵌套、命名视图、动态增删路由一气呵成。一句话:写更少,跑更快,体验更丝滑。

Vue Router 4 终极速通表_字符串

核心概念
  • 路由 (Route): URL 路径与组件的映射关系
  • 路由器 (Router): 管理所有路由的实例
  • 导航 (Navigation): 从一个路由切换到另一个路由的过程
安装
npm install vue-router@4
基础配置
// src/router/index.js
import { createRouter, createWebHistory } from'vue-router'
import Home from'@/views/Home.vue'
import About from'@/views/About.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: About
  }
]

const router = createRouter({
history: createWebHistory(),
  routes
})

exportdefault router
在应用中使用
// src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

const app = createApp(App)
app.use(router)
app.mount('#app')
1. 基础路由配置
const routes = [
// 基础路由
  {
    path: '/',
    name: 'Home',
    component: Home
  },

// 带参数的路由
  {
    path: '/user/:id',
    name: 'User',
    component: User,
    props: true// 将路由参数作为 props 传递给组件
  },

// 可选参数
  {
    path: '/user/:id?',
    name: 'UserOptional',
    component: User
  },

// 多个参数
  {
    path: '/user/:id/post/:postId',
    name: 'UserPost',
    component: UserPost
  },

// 通配符路由 (404 页面)
  {
    path: '/:pathMatch(.*)*',
    name: 'NotFound',
    component: NotFound
  }
]
2. 嵌套路由
const routes = [
  {
    path: '/user/:id',
    component: User,
    children: [
      // 空路径表示默认子路由
      { path: '', component: UserHome },
      
      // 子路由
      { path: 'profile', component: UserProfile },
      { path: 'posts', component: UserPosts },
      
      // 嵌套的动态路由
      { path: 'posts/:postId', component: UserPost }
    ]
  }
]
3. 命名视图
const routes = [
  {
    path: '/',
    components: {
      default: Home,
      sidebar: Sidebar,
      header: Header
    }
  }
]
4. 路由懒加载
const routes = [
  {
    path: '/about',
    name: 'About',
    // 路由级别的代码分割
    component: () =>import('@/views/About.vue')
  },

// 带有自定义 chunk 名称
  {
    path: '/admin',
    name: 'Admin',
    component: () =>import(/* webpackChunkName: "admin" */'@/views/Admin.vue')
  }
]
1. 声明式导航
<template>
  <!-- 基础导航 -->
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>

<!-- 命名路由导航 -->
<router-link :to="{ name: 'User', params: { id: 123 } }">用户</router-link>

<!-- 带查询参数 -->
<router-link :to="{ path: '/search', query: { q: 'vue' } }">搜索</router-link>

<!-- 带 hash -->
<router-link :to="{ path: '/about', hash: '#team' }">关于团队</router-link>

<!-- 替换历史记录 -->
<router-link :to="{ path: '/home' }" replace>首页</router-link>

<!-- 自定义激活类名 -->
<router-link 
    to="/about" 
    active-class="active"
    exact-active-class="exact-active"
  >
    关于
</router-link>
</template>
2. 编程式导航
// 在组件中使用
exportdefault {
methods: {
    navigateToUser() {
      // 字符串路径
      this.$router.push('/user/123')
      
      // 对象形式
      this.$router.push({ path: '/user/123' })
      
      // 命名路由
      this.$router.push({ name: 'User', params: { id: 123 } })
      
      // 带查询参数
      this.$router.push({ path: '/search', query: { q: 'vue' } })
      
      // 替换当前历史记录
      this.$router.replace({ name: 'Home' })
      
      // 前进/后退
      this.$router.go(-1) // 后退一步
      this.$router.go(1)  // 前进一步
      this.$router.back() // 后退
      this.$router.forward() // 前进
    }
  }
}
3. 组合式 API 中的导航
import { useRouter, useRoute } from'vue-router'

exportdefault {
  setup() {
    const router = useRouter()
    const route = useRoute()
    
    const navigateToUser = () => {
      router.push({ name: 'User', params: { id: 123 } })
    }
    
    // 获取当前路由信息
    console.log(route.path)
    console.log(route.params)
    console.log(route.query)
    
    return {
      navigateToUser
    }
  }
}
1. 全局守卫
// 全局前置守卫
router.beforeEach((to, from, next) => {
// to: 即将要进入的目标路由对象
// from: 当前导航正要离开的路由
// next: 一定要调用该方法来 resolve 这个钩子

console.log('导航到:', to.path)
console.log('来自:', from.path)

// 检查用户认证
if (to.matched.some(record => record.meta.requiresAuth)) {
    if (!isAuthenticated()) {
      next({ name: 'Login' })
    } else {
      next()
    }
  } else {
    next()
  }
})

// 全局解析守卫
router.beforeResolve((to, from, next) => {
// 在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后调用
  next()
})

// 全局后置钩子
router.afterEach((to, from) => {
// 这些钩子不会接受 next 函数也不会改变导航本身
console.log('导航完成')

// 更新页面标题
document.title = to.meta.title || 'Default Title'
})
2. 路由独享守卫
const routes = [
  {
    path: '/admin',
    component: Admin,
    beforeEnter: (to, from, next) => {
      // 只在进入该路由时调用
      if (hasAdminPermission()) {
        next()
      } else {
        next('/unauthorized')
      }
    }
  }
]
3. 组件内守卫
export default {
// 进入路由前
  beforeRouteEnter(to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不能获取组件实例 `this`,因为当守卫执行前,组件实例还没被创建
    next(vm => {
      // 通过 `vm` 访问组件实例
    })
  },

// 路由更新时
  beforeRouteUpdate(to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 例如,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
    next()
  },

// 离开路由前
  beforeRouteLeave(to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
    const answer = window.confirm('确定要离开吗?未保存的更改将会丢失。')
    if (answer) {
      next()
    } else {
      next(false)
    }
  }
}
4. 组合式 API 中的守卫
import { onBeforeRouteLeave, onBeforeRouteUpdate } from'vue-router'

exportdefault {
  setup() {
    // 与 beforeRouteLeave 相同,无法访问 `this`
    onBeforeRouteLeave((to, from) => {
      const answer = window.confirm('确定要离开吗?')
      if (!answer) returnfalse
    })
    
    // 与 beforeRouteUpdate 相同
    onBeforeRouteUpdate(async (to, from) => {
      if (to.params.id !== from.params.id) {
        await fetchUser(to.params.id)
      }
    })
  }
}
1. useRouter 和 useRoute
import { useRouter, useRoute } from'vue-router'
import { computed, watch } from'vue'

exportdefault {
  setup() {
    const router = useRouter()
    const route = useRoute()
    
    // 响应式的路由参数
    const userId = computed(() => route.params.id)
    
    // 监听路由变化
    watch(
      () => route.params.id,
      (newId, oldId) => {
        console.log(`用户ID从 ${oldId} 变为 ${newId}`)
      }
    )
    
    // 导航方法
    const goToUser = (id) => {
      router.push({ name: 'User', params: { id } })
    }
    
    return {
      userId,
      goToUser
    }
  }
}
2. useLink
import { useLink } from'vue-router'

exportdefault {
props: {
    to: {
      type: [String, Object],
      required: true
    }
  },
  setup(props) {
    const { href, navigate, isActive, isExactActive } = useLink(props)
    
    return {
      href,
      navigate,
      isActive,
      isExactActive
    }
  }
}
1. 路由元信息
const routes = [
  {
    path: '/admin',
    component: Admin,
    meta: {
      requiresAuth: true,
      title: '管理后台',
      roles: ['admin', 'moderator']
    }
  }
]

// 在组件中访问
exportdefault {
  created() {
    console.log(this.$route.meta.title)
  }
}
2. 过渡效果
<template>
  <router-view v-slot="{ Component, route }">
    <transition :name="route.meta.transition || 'fade'">
      <component :is="Component" :key="route.path" />
    </transition>
  </router-view>
</template>

<style>
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.3s;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}
</style>
3. 滚动行为
const router = createRouter({
history: createWebHistory(),
  routes,
  scrollBehavior(to, from, savedPosition) {
    // 如果有保存的位置(浏览器前进/后退)
    if (savedPosition) {
      return savedPosition
    }
    
    // 如果有锚点
    if (to.hash) {
      return {
        el: to.hash,
        behavior: 'smooth'
      }
    }
    
    // 默认滚动到顶部
    return { top: 0 }
  }
})
4. 动态路由
// 添加路由
router.addRoute({
path: '/dynamic',
name: 'Dynamic',
component: DynamicComponent
})

// 添加嵌套路由
router.addRoute('Parent', {
path: 'child',
name: 'Child',
component: ChildComponent
})

// 删除路由
router.removeRoute('Dynamic')

// 检查路由是否存在
if (router.hasRoute('Dynamic')) {
console.log('路由存在')
}

// 获取所有路由
const routes = router.getRoutes()
Router 实例方法
// 导航方法
router.push(location, onComplete?, onAbort?)
router.replace(location, onComplete?, onAbort?)
router.go(n)
router.back()
router.forward()

// 路由管理
router.addRoute(route)
router.addRoute(parentName, route)
router.removeRoute(name)
router.hasRoute(name)
router.getRoutes()

// 解析方法
router.resolve(location, current?, append?)

// 守卫方法
router.beforeEach(guard)
router.beforeResolve(guard)
router.afterEach(hook)

// 历史记录
router.isReady()
router.currentRoute
Route 对象属性
// 当前路由信息
route.path          // 字符串,对应当前路由的路径
route.params        // 对象,包含动态片段和全匹配片段的键值对
route.query         // 对象,表示 URL 查询参数
route.hash          // 字符串,当前路由的 hash 值
route.fullPath      // 字符串,完整路径
route.matched       // 数组,包含当前路由的所有嵌套路径片段的路由记录
route.name          // 字符串,当前路由的名称
route.redirectedFrom // 如果存在重定向,即为重定向来源的路由的名字
route.meta          // 路由元信息
RouterLink Props
// RouterLink 组件属性
to              // 目标路由的链接
replace         // 是否替换当前历史记录
activeClass     // 激活时的 CSS 类名
exactActiveClass // 精确激活时的 CSS 类名
custom          // 是否阻止默认行为
RouterView Props
// RouterView 组件属性
name            // 命名视图的名称
route           // 显式指定要渲染的路由
完整的路由配置示例
// src/router/index.js
import { createRouter, createWebHistory } from'vue-router'
import { useAuthStore } from'@/stores/auth'

// 路由组件
const Home = () =>import('@/views/Home.vue')
const Login = () =>import('@/views/Login.vue')
const Dashboard = () =>import('@/views/Dashboard.vue')
const Profile = () =>import('@/views/Profile.vue')
const NotFound = () =>import('@/views/NotFound.vue')

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home,
    meta: {
      title: '首页'
    }
  },
  {
    path: '/login',
    name: 'Login',
    component: Login,
    meta: {
      title: '登录',
      guest: true
    }
  },
  {
    path: '/dashboard',
    name: 'Dashboard',
    component: Dashboard,
    meta: {
      title: '仪表板',
      requiresAuth: true
    }
  },
  {
    path: '/profile',
    name: 'Profile',
    component: Profile,
    meta: {
      title: '个人资料',
      requiresAuth: true
    }
  },
  {
    path: '/:pathMatch(.*)*',
    name: 'NotFound',
    component: NotFound,
    meta: {
      title: '页面未找到'
    }
  }
]

const router = createRouter({
history: createWebHistory(),
  routes,
  scrollBehavior(to, from, savedPosition) {
    if (savedPosition) {
      return savedPosition
    }
    return { top: 0 }
  }
})

// 全局前置守卫
router.beforeEach(async (to, from, next) => {
const authStore = useAuthStore()

// 设置页面标题
document.title = to.meta.title || 'My App'

// 检查认证状态
if (to.meta.requiresAuth && !authStore.isAuthenticated) {
    next({ name: 'Login', query: { redirect: to.fullPath } })
  } elseif (to.meta.guest && authStore.isAuthenticated) {
    next({ name: 'Dashboard' })
  } else {
    next()
  }
})

exportdefault router
在组件中使用路由
<template>
  <div>
    <!-- 导航菜单 -->
    <nav>
      <router-link to="/" exact-active-class="active">首页</router-link>
      <router-link to="/dashboard" active-class="active">仪表板</router-link>
      <router-link to="/profile" active-class="active">个人资料</router-link>
    </nav>
    
    <!-- 路由视图 -->
    <router-view v-slot="{ Component, route }">
      <transition name="fade" mode="out-in">
        <component :is="Component" :key="route.path" />
      </transition>
    </router-view>
</div>
</template>

<script>
import { useRouter, useRoute } from'vue-router'
import { computed } from'vue'

exportdefault {
  setup() {
    const router = useRouter()
    const route = useRoute()
    
    // 当前路径
    const currentPath = computed(() => route.path)
    
    // 导航方法
    const navigateTo = (path) => {
      router.push(path)
    }
    
    // 返回上一页
    const goBack = () => {
      router.go(-1)
    }
    
    return {
      currentPath,
      navigateTo,
      goBack
    }
  }
}
</script>

<style>
.active {
color: #42b983;
font-weight: bold;
}

.fade-enter-active, .fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
</style>
1. 路由结构组织
// 按功能模块组织路由
const routes = [
// 公共路由
  ...publicRoutes,

// 用户相关路由
  ...userRoutes,

// 管理员路由
  ...adminRoutes,

// 404 路由(放在最后)
  ...notFoundRoutes
]
2. 路由懒加载最佳实践
// 按页面分组
const UserRoutes = [
  {
    path: '/user',
    component: () =>import(/* webpackChunkName: "user" */'@/layouts/UserLayout.vue'),
    children: [
      {
        path: 'profile',
        component: () =>import(/* webpackChunkName: "user" */'@/views/user/Profile.vue')
      },
      {
        path: 'settings',
        component: () =>import(/* webpackChunkName: "user" */'@/views/user/Settings.vue')
      }
    ]
  }
]
3. 类型安全(TypeScript)
// 路由类型定义
import { RouteRecordRaw } from'vue-router'

declaremodule 'vue-router' {
interface RouteMeta {
    title?: string
    requiresAuth?: boolean
    roles?: string[]
  }
}

const routes: RouteRecordRaw[] = [
  {
    path: '/admin',
    component: () =>import('@/views/Admin.vue'),
    meta: {
      title: '管理后台',
      requiresAuth: true,
      roles: ['admin']
    }
  }
]

这份教程涵盖了 Vue Router 4.x 的所有主要 API 和使用方法,从基础配置到高级特性,应该能满足你的学习和开发需求