package.json 中的 `vue-router` 详解

package.json 中的 vue-router 详解

vue-router 是 Vue 官方提供的前端路由库,主要用于 Vue 单页应用中不同页面之间的切换。

例如:

bash 复制代码
/login       登录页
/home        首页
/user        用户列表
/user/1001   用户详情

这些地址对应不同的 Vue 组件,但切换时通常不会重新加载整个网页。


1. package.json 中的 vue-router

通常会看到:

json 复制代码
{
  "dependencies": {
    "vue": "^3.5.0",
    "vue-router": "^4.5.0"
  }
}

这里:

json 复制代码
"vue-router": "^4.5.0"

各部分含义如下:

  • vue-router:依赖包名称。
  • 4.5.0:安装的版本范围基准。
  • ^:允许安装兼容的较新版本。

版本号一般由三部分组成:

复制代码
4.5.0
│ │ │
│ │ └─ 补丁版本 patch
│ └─── 次版本 minor
└───── 主版本 major

^4.5.0 一般允许升级到:

shell 复制代码
>= 4.5.0,并且 < 5.0.0

例如可能安装:

复制代码
4.5.1
4.6.0
4.9.0

但不会自动升级到:

复制代码
5.0.0

Vue 3 对应的是 Vue Router 4:

复制代码
Vue 2 → vue-router 3
Vue 3 → vue-router 4

2. 为什么放在 dependencies 中?

dependencies 存放项目运行时需要的依赖:

json 复制代码
{
  "dependencies": {
    "vue": "^3.5.0",
    "vue-router": "^4.5.0",
    "axios": "^1.11.0"
  }
}

项目运行时,需要 vue-router 完成页面路由切换,所以它通常放在 dependencies 中。

而下面这些构建工具一般放在 devDependencies:

json 复制代码
{
  "devDependencies": {
    "typescript": "^5.8.0",
    "vite": "^7.0.0",
    "eslint": "^9.0.0"
  }
}

简单理解:

  • dependencies:程序运行需要。
  • devDependencies:开发、检查、编译时需要。

3. 安装 Vue Router

使用 npm:

复制代码
npm install vue-router

使用 pnpm:

csharp 复制代码
pnpm add vue-router

指定 Vue Router 4:

css 复制代码
npm install vue-router@4

安装后,package.json 中会自动出现:

json 复制代码
{
  "dependencies": {
    "vue-router": "^4.5.0"
  }
}

同时依赖代码会被下载到:

bash 复制代码
node_modules/vue-router

锁文件中也会记录准确版本:

csharp 复制代码
package-lock.json
pnpm-lock.yaml
yarn.lock

不要只手动修改 package.json 而不执行安装,否则 node_modules 中可能没有这个包。


Vue Router 的基本配置

4. 创建页面组件

假设项目结构如下:

css 复制代码
src/
├─ views/
│  ├─ Home.vue
│  ├─ Login.vue
│  └─ User.vue
├─ router/
│  └─ index.ts
├─ App.vue
└─ main.ts

Home.vue:

xml 复制代码
<template>
  <div>首页</div>
</template>

Login.vue:

xml 复制代码
<template>
  <div>登录页</div>
</template>

5. 创建路由配置

在 src/router/index.ts 中:

javascript 复制代码
import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: () => import('@/views/Home.vue'),
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/Login.vue'),
  },
]

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

export default router

这里主要做了三件事:

  1. 定义地址和页面组件的对应关系。
  2. 创建路由实例。
  3. 导出路由实例。

6. createRouter

css 复制代码
const router = createRouter({
  history: createWebHistory(),
  routes,
})

createRouter() 用于创建路由对象。

它接收一个配置对象:

yaml 复制代码
{
  history: 路由模式,
  routes: 路由规则数组
}

创建完成后,router 负责:

  • 监听浏览器地址变化。
  • 根据地址找到对应组件。
  • 控制页面组件切换。
  • 管理前进、后退。
  • 执行路由守卫。

7. routes 路由表

javascript 复制代码
const routes = [
  {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/Login.vue'),
  },
]

每个对象就是一条路由规则。

path

lua 复制代码
path: '/login'

表示浏览器地址:

bash 复制代码
http://localhost:5173/login

访问 /login 时,显示该路由对应的组件。

name

vbnet 复制代码
name: 'Login'

表示路由名称。

可以通过名称跳转:

css 复制代码
router.push({
  name: 'Login',
})

建议每条重要路由的 name 保持唯一。

component

javascript 复制代码
component: () => import('@/views/Login.vue')

表示访问该路由时加载哪个 Vue 组件。

这种写法叫动态导入或懒加载:用户访问这个页面时才加载对应文件,有利于减少首页资源体积。

也可以直接导入:

javascript 复制代码
import Login from '@/views/Login.vue'

const routes = [
  {
    path: '/login',
    component: Login,
  },
]

直接导入通常会把页面组件放进初始资源中。实际项目的页面路由通常更常使用懒加载。


在 Vue 应用中注册路由

8. 修改 main.ts

javascript 复制代码
import { createApp } from 'vue'

import App from './App.vue'
import router from './router'

const app = createApp(App)

app.use(router)

app.mount('#app')

最关键的是:

php 复制代码
app.use(router)

它把路由插件安装到整个 Vue 应用中。

注册后,组件中才能使用:

  • <RouterView>
  • <RouterLink>
  • useRouter()
  • useRoute()

一般要在:

arduino 复制代码
app.mount('#app')

之前注册。


显示路由页面

9. RouterView

在 App.vue 中:

xml 复制代码
<template>
  <RouterView />
</template>

<RouterView /> 是路由页面的显示位置,可以理解为一个页面出口。

如果当前地址是:

bash 复制代码
/login

RouterView 会显示:

复制代码
Login.vue

如果当前地址是:

复制代码
/

它会显示:

复制代码
Home.vue

如果没有写 <RouterView />,浏览器地址可能改变了,但对应页面组件没有地方显示。


声明式路由跳转可以使用:

xml 复制代码
<template>
  <RouterLink to="/">
    首页
  </RouterLink>

  <RouterLink to="/login">
    登录页
  </RouterLink>

  <RouterView />
</template>

它最终通常会生成类似 <a> 的元素,但由 Vue Router 控制跳转,不会像普通链接一样重新加载整个页面。

根据路由名称跳转:

ini 复制代码
<RouterLink :to="{ name: 'Login' }">
  登录页
</RouterLink>

在代码中跳转页面

11. useRouter

useRouter() 获取整个路由实例,主要用于执行跳转。

xml 复制代码
<script lang="ts" setup>
import { useRouter } from 'vue-router'

const router = useRouter()

function goLogin() {
  router.push('/login')
}
</script>

<template>
  <button @click="goLogin">
    去登录页
  </button>
</template>

根据路由名称跳转:

css 复制代码
router.push({
  name: 'Login',
})

返回上一页:

scss 复制代码
router.back()

前进:

scss 复制代码
router.forward()

前进或后退指定层数:

go 复制代码
router.go(-1)
router.go(1)

12. push 和 replace 的区别

router.push

arduino 复制代码
router.push('/home')

会在浏览器历史记录中增加一条记录。

例如:

复制代码
登录页 → 首页

在首页点击浏览器后退,可以回到登录页。

router.replace

arduino 复制代码
router.replace('/home')

会替换当前历史记录。

例如登录成功后:

arduino 复制代码
router.replace('/home')

用户点击后退时,通常不会再次回到登录页面。

简单理解:

  • push:新增历史记录。
  • replace:替换当前历史记录。

获取当前路由信息

13. useRoute

useRoute() 用于获取当前页面的路由信息:

xml 复制代码
<script lang="ts" setup>
import { useRoute } from 'vue-router'

const route = useRoute()

console.log(route.path)
console.log(route.name)
console.log(route.params)
console.log(route.query)
</script>

注意区别:

ini 复制代码
const router = useRouter()
const route = useRoute()
  • router:负责跳转和控制路由。
  • route:保存当前路由的信息。

可以记成:

复制代码
router:路由控制器
route:当前路由数据

路由参数

14. 动态参数 params

路由配置:

css 复制代码
{
  path: '/user/:id',
  name: 'UserDetail',
  component: () => import('@/views/UserDetail.vue'),
}

这里:

bash 复制代码
:id

表示动态参数。

访问:

bash 复制代码
/user/1001

其中 1001 就是 id。

组件中获取:

javascript 复制代码
import { useRoute } from 'vue-router'

const route = useRoute()

console.log(route.params.id) // 1001

跳转:

php 复制代码
router.push({
  name: 'UserDetail',
  params: {
    id: 1001,
  },
})

结果地址:

bash 复制代码
/user/1001

通过 params 跳转时,推荐使用路由名称 name。


15. 查询参数 query

跳转:

php 复制代码
router.push({
  path: '/user',
  query: {
    page: 1,
    keyword: 'camera',
  },
})

最终地址:

ini 复制代码
/user?page=1&keyword=camera

获取参数:

scss 复制代码
const route = useRoute()

console.log(route.query.page)
console.log(route.query.keyword)

params 和 query 的区别

params:

bash 复制代码
/user/1001

获取:

csharp 复制代码
route.params.id

query:

bash 复制代码
/user?id=1001

获取:

python 复制代码
route.query.id

一般来说:

  • 用户、文章详情 ID:常用 params。
  • 搜索、分页、筛选条件:常用 query。

嵌套路由

16. children

例如用户中心包含个人信息和设置:

javascript 复制代码
const routes = [
  {
    path: '/user',
    component: () => import('@/views/UserLayout.vue'),
    children: [
      {
        path: 'profile',
        component: () => import('@/views/UserProfile.vue'),
      },
      {
        path: 'settings',
        component: () => import('@/views/UserSettings.vue'),
      },
    ],
  },
]

访问地址:

bash 复制代码
/user/profile
/user/settings

父组件 UserLayout.vue 必须提供子路由出口:

xml 复制代码
<template>
  <div>
    <h2>用户中心</h2>

    <RouterView />
  </div>
</template>

注意子路由通常写成:

lua 复制代码
path: 'profile'

而不是:

lua 复制代码
path: '/profile'

不带 / 表示它相对于父路由 /user。


路由重定向与 404

17. redirect

访问一个地址后自动跳转到另一个地址:

css 复制代码
{
  path: '/',
  redirect: '/home',
}

也可以按照名称:

css 复制代码
{
  path: '/',
  redirect: {
    name: 'Home',
  },
}

18. 404 路由

css 复制代码
{
  path: '/:pathMatch(.*)*',
  name: 'NotFound',
  component: () => import('@/views/NotFound.vue'),
}

这条路由表示匹配前面路由都没有匹配到的地址。

通常放在路由数组最后:

javascript 复制代码
const routes = [
  // 正常页面路由

  {
    path: '/:pathMatch(.*)*',
    component: () => import('@/views/NotFound.vue'),
  },
]

路由元信息

19. meta

可以给路由添加额外信息:

css 复制代码
{
  path: '/admin',
  name: 'Admin',
  component: () => import('@/views/Admin.vue'),
  meta: {
    title: '后台管理',
    requiresAuth: true,
  },
}

读取:

scss 复制代码
const route = useRoute()

console.log(route.meta.title)
console.log(route.meta.requiresAuth)

常见用途:

  • 页面标题。
  • 是否需要登录。
  • 用户权限。
  • 菜单图标。
  • 是否显示侧边栏。
  • 页面缓存设置。

路由守卫

20. beforeEach

全局前置守卫在每次路由跳转前执行:

javascript 复制代码
router.beforeEach((to, from) => {
  console.log('准备进入:', to.path)
  console.log('从哪里来:', from.path)
})

参数含义:

  • to:准备进入的路由。
  • from:当前准备离开的路由。

登录验证示例:

javascript 复制代码
router.beforeEach((to) => {
  const token = localStorage.getItem('token')

  if (to.meta.requiresAuth && !token) {
    return {
      name: 'Login',
    }
  }
})

含义是:

复制代码
目标页面需要登录
并且当前没有 token
→ 跳转到登录页

允许继续进入时,可以不返回内容:

javascript 复制代码
router.beforeEach(() => {
  // 不返回,继续跳转
})

现在更推荐直接返回跳转位置,不必使用旧式的 next()。


21. 修改浏览器标题

结合 meta:

javascript 复制代码
router.afterEach((to) => {
  document.title = String(to.meta.title ?? '管理系统')
})

路由:

css 复制代码
{
  path: '/home',
  meta: {
    title: '首页',
  },
}

访问首页后,浏览器标签标题会变成"首页"。


路由模式

22. createWebHistory

bash 复制代码
history: createWebHistory()

地址比较正常:

arduino 复制代码
https://example.com/home
https://example.com/user

优点是地址美观。

但部署到服务器时,需要服务器支持:当用户直接访问 /user 时,服务器应该返回项目的 index.html,交给 Vue Router 处理。

否则刷新页面可能出现 404。


23. createWebHashHistory

javascript 复制代码
import {
  createRouter,
  createWebHashHistory,
} from 'vue-router'

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

地址带有 #:

bash 复制代码
https://example.com/#/home
https://example.com/#/user

优点:

  • 服务器通常不需要额外配置。
  • 刷新页面不容易出现 404。

缺点:

  • 地址中有 #,不如 history 模式美观。

简单选择:

  • 正常 Web 项目并且服务器可以配置:createWebHistory()。
  • 无法配置服务器或简单静态部署:可以考虑 createWebHashHistory()。

常见完整配置

javascript 复制代码
import {
  createRouter,
  createWebHistory,
} from 'vue-router'

const routes = [
  {
    path: '/',
    redirect: '/home',
  },
  {
    path: '/home',
    name: 'Home',
    component: () => import('@/views/Home.vue'),
    meta: {
      title: '首页',
      requiresAuth: true,
    },
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/Login.vue'),
    meta: {
      title: '登录',
      requiresAuth: false,
    },
  },
  {
    path: '/user/:id',
    name: 'UserDetail',
    component: () => import('@/views/UserDetail.vue'),
    meta: {
      title: '用户详情',
      requiresAuth: true,
    },
  },
  {
    path: '/:pathMatch(.*)*',
    name: 'NotFound',
    component: () => import('@/views/NotFound.vue'),
  },
]

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

router.beforeEach((to) => {
  const token = localStorage.getItem('token')

  if (to.meta.requiresAuth && !token) {
    return {
      name: 'Login',
      query: {
        redirect: to.fullPath,
      },
    }
  }
})

router.afterEach((to) => {
  document.title = String(to.meta.title ?? '管理系统')
})

export default router

main.ts:

javascript 复制代码
import { createApp } from 'vue'

import App from './App.vue'
import router from './router'

createApp(App)
  .use(router)
  .mount('#app')

App.vue:

xml 复制代码
<template>
  <RouterView />
</template>

初学者重点记忆

csharp 复制代码
vue-router:Vue官方路由库
routes:地址和页面组件的对应关系
createRouter:创建路由实例
createWebHistory:选择路由模式
app.use(router):把路由注册到Vue应用
RouterView:显示当前路由对应的组件
RouterLink:声明式跳转
useRouter:执行路由跳转
useRoute:获取当前路由信息
params:路径参数
query:查询参数
children:嵌套路由
meta:路由附加信息
beforeEach:跳转前执行权限检查

最容易混淆的是:

scss 复制代码
const router = useRouter() // 用来跳转
const route = useRoute()   // 用来读取当前路由

例如:

scss 复制代码
const router = useRouter()
const route = useRoute()

console.log(route.params.id)

router.push('/home')
相关推荐
cidy_981 小时前
第 3 章:工作台——数据看板
前端
国奉1 小时前
iOS 音频格式转换怎么实现?从 AVAudioFile、AAC、MP3 到 FLAC 与批量转码架构
前端·后端
呃呃呃呃ex1 小时前
3. JavaScript 异步编程:Promise、async/await、Generator 与异步调度
前端·javascript
IT_陈寒1 小时前
Vite的静态资源引用把我坑惨了
前端·人工智能·后端
风骏时光牛马1 小时前
AI工作流全链路自动化落地实践
前端
kyriewen1 小时前
5 次优化让首屏快 3.6 秒,只有 1 次是改代码
前端·javascript·程序员
编程老船长1 小时前
模型中立——把大模型做成"可替换零件",而不是焊死在业务里
java·前端·后端
禁止摆烂_才浅1 小时前
Axios 完整封装合集(鉴权 + 重复拦截 + Loading + 缓存 + 统一错误 + 请求重试|全代码逐行注释)
前端·javascript·axios
陈随易1 小时前
傻瓜式UX:ERP的致命糖衣
前端·后端·程序员