Code前端首页关于Code前端联系我们

1.vue-router.js 到底是个啥工具?

terry 6小时前 阅读数 9 #Vue
文章标签 router 路由工具

前端开发里,Vue.js 生态的路由工具 vue-router.js 算是“必学技能”,但不少刚入门的同学总会犯懵:它到底是干啥的?咋在项目里用?遇到路由跳转失效、页面不更新这些问题咋解决?今天咱就用问答形式,把 vue-router 的关键知识点和开发坑点一次性讲清楚~

简单说,vue-router 是 Vue 官方出的路由管理器,专门帮单页应用(SPA)实现“无刷新页面跳转”和“组件切换”。

举个现实例子:传统多页网站点“首页”“,浏览器会整页刷新换内容;但 SPA (比如用 Vue 做的后台管理系统)点导航时,页面不刷新,只是局部换组件,vue-router 就是背后的“导航指挥官”——它决定哪个路径对应哪个组件,还能管理导航过程(比如权限验证、传参)。

要是没它,你得自己写代码监听 URL 变化、手动切换组件,不仅麻烦还容易搞出 bug,所以做中大型 Vue 项目,vue-router 几乎是标配。

为啥做 SPA 必须得用 vue-router?自己写路由不行吗?

不是不能自己写,但vue-router 把路由逻辑封装得特别顺手,省了超多重复劳动,它至少解决了这几个核心问题:

  • 声明式导航:用 <router-link> 组件写导航,不用手动写 window.location,还能自动处理“当前页面高亮”这类样式逻辑;
  • 编程式导航:在 JS 里用 this.$router.push() 跳转,比如登录成功后跳首页,逻辑里调一行代码就搞定;
  • 路由嵌套:像后台系统的“布局页 + 子页面”结构(比如侧边栏固定,中间内容换),用路由嵌套能少写很多重复代码;
  • 参数传递 & 权限控制:动态路由传参(/user/123)、查询参数(?id=123)、路由守卫(跳转前验权)这些功能,自己实现得写一堆判断逻辑,vue-router 直接给现成 API;

要是硬自己写,光处理“URL 变化但页面不刷新”“组件复用导致数据不更新”这些细节,就能把人折腾疯,所以除非做极简单的 Demo,否则直接用官方路由更高效。

vue-router 基础使用步骤是啥样的?(拿小项目举例子)

咱以“做个有首页和关于页的小 SPA”为例,走一遍流程:

步骤 1:安装 vue-router

如果是 Vue2 项目,用 npm install vue-router@3;Vue3 项目则用 npm install vue-router@4(版本差异后面讲),也可以用 CDN 直接引入,但项目里一般用包管理工具。

步骤 2:配置路由规则

新建个 router 文件夹,里面建 index.js,写路由规则:

// Vue2 版本示例
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/components/Home.vue'
import About from '@/components/About.vue'

Vue.use(VueRouter) // 注册路由插件

const routes = [ { path: '/', component: Home }, // 根路径对应 Home 组件 { path: '/about', component: About } // /about 对应 About 组件 ]

const router = new VueRouter({ routes // 把规则传给路由实例 })

export default router

(Vue3 版本写法不同,后面“Vue3 配合”部分详细说)

步骤 3:把路由注入 Vue 根实例

打开项目入口文件 main.js,把路由实例挂到 Vue 上:

// Vue2 示例
import Vue from 'vue'
import App from './App.vue'
import router from './router' // 引入上面写的路由配置

new Vue({ router, // 注入路由 render: h => h(App) }).$mount('#app')

步骤 4:在页面里用路由组件

App.vue 这类根组件里,用 <router-link> 做导航,用 <router-view> 显示匹配的组件:

<template>
  <div id="app">
    <!-- 声明式导航:点“首页”跳 /,点“跳 /about -->
    <router-link to="/">首页</router-link>
    <router-link to="/about">lt;/router-link>
&lt;!-- 匹配到的组件会渲染到这里 --&gt;
&lt;router-view&gt;&lt;/router-view&gt;

</div> </template>

这样一配,点导航时页面就会无刷新切换组件啦~

路由传参有哪几种方式?分别适合啥场景?

开发里经常需要“跳转时带数据”,比如从列表页点用户头像,跳转到用户详情页并传用户 ID,vue-router 有三种常用传参方式,各有适用场景:

方式 1:动态路由(用 params 传参)

配置路由时,路径里加动态段,path: '/user/:id';跳转时用 <router-link to="/user/123"> 或者 this.$router.push('/user/123');组件里用 this.$route.params.id 取参数。

适合场景:参数是“资源唯一标识”(比如用户 ID、商品 ID),且希望参数显示在 URL 里(刷新页面参数不会丢),像电商详情页 /goods/1001 这种场景常用。

方式 2:查询参数(用 query 传参)

配置路由时路径正常写(path: '/user'),跳转时带查询参数,像 <router-link to="/user?id=123"> 或者 this.$router.push({ path: '/user', query: { id: 123 } });组件里用 this.$route.query.id 取参数。

适合场景:参数不是核心标识(比如搜索页的关键词、分页页码),或者需要传多个非关键参数,URL 里会显示 ?id=123&page=2 这类结构,刷新也能保留。

方式 3:路由元信息(meta 传参)

配置路由时,给路由对象加 meta 字段,

{
  path: '/admin',
  component: Admin,
  meta: { requiresAuth: true, title: '后台管理' }
}

组件里用 this.$route.meta.requiresAuth 取配置;也能在路由守卫里用(比如判断是否需要登录)。

适合场景:给“页面级别”加配置信息(比如是否需要权限、页面标题),这些信息不需要显示在 URL 里,只在代码里判断用。

总结下:要让参数在 URL 里、当资源标识用 params;要传多个非关键参数、URL 可带?用 query;要给页面加配置用 meta。

路由嵌套是咋实现的?实际项目哪块会用到?

路由嵌套指的是“一个页面里包含子页面”,典型场景是后台管理系统的布局页——比如侧边栏和顶栏是固定的,中间内容区根据不同路由显示不同子页面(仪表盘、用户管理、订单管理等)。

实现分两步:

步骤 1:配置嵌套路由规则

在父路由的 children 数组里写子路由,

const routes = [
  {
    path: '/dashboard',
    component: DashboardLayout, // 父组件(包含侧边栏、顶栏)
    children: [
      { path: 'home', component: DashboardHome }, // 子路由,路径是 /dashboard/home
      { path: 'stats', component: DashboardStats } // 子路由,路径是 /dashboard/stats
    ]
  }
]

步骤 2:父组件模板里加 <router-view>

DashboardLayout.vue 里,侧边栏和顶栏代码之外,留个 <router-view> 给子组件:

<template>
  <div class="dashboard-layout">
    <aside>侧边栏</aside>
    <header>顶栏</header>
    <main>
      <!-- 子组件会渲染到这里 -->
      <router-view></router-view>
    </main>
  </div>
</template>

这样访问 /dashboard/home 时,DashboardLayout 会渲染,中间 <router-view> 显示 DashboardHome 组件,实际项目里,只要有“公共布局 + 多个子页面”的结构,都适合用路由嵌套,能少写很多重复的布局代码。

声明式导航和编程式导航有啥区别?该咋选?

vue-router 提供了两种导航方式,核心区别是“在哪写导航逻辑”

声明式导航:用 <router-link> 组件

直接在模板里写,

<router-link to="/home">回首页</router-link>

优点:简单直观,vue-router 会自动把它渲染成 <a> 标签,还能自动处理“当前页面高亮”(通过 active-class 属性);
适合场景:导航栏、菜单按钮这些“模板里能看到的导航”,比如页面顶部的 Tab 栏、侧边栏菜单。

编程式导航:用 this.$router.push() 等方法

在 JS 逻辑里写,比如登录成功后跳转:

methods: {
  handleLogin() {
    // 登录逻辑...
    this.$router.push('/home') // 登录成功后跳转到首页
  }
}

优点:灵活,能在任意 JS 逻辑里触发导航(Ajax 回调、定时器里);
适合场景:需要“逻辑判断后再跳转”的情况,比如登录校验、表单提交成功后跳转。

模板里能写死的导航用声明式,逻辑里动态判断的导航用编程式

路由守卫是干啥的?咋用它做权限控制?

路由守卫可以理解成“路由跳转过程中的钩子函数”,能在“跳转前、跳转后、组件复用前”这些时机插逻辑,最常用的场景是权限控制(比如判断用户是否登录,没登录就拦截到登录页)。

vue-router 有三类守卫,咱重点讲全局守卫(控制所有路由)和路由独享守卫(控制单个路由):

全局守卫:router.beforeEach

在路由配置文件里,给 router 实例加全局前置守卫:

router.beforeEach((to, from, next) => {
  // to:要跳转到的目标路由对象
  // from:从哪个路由跳过来的
  // next:放行函数,必须调用才能继续跳转
  if (to.meta.requiresAuth) { // 检查目标路由是否需要权限
    if (isLogin()) { // 假设 isLogin() 是判断登录状态的函数
      next() // 已登录,放行
    } else {
      next('/login') // 没登录,跳转到登录页
    }
  } else {
    next() // 不需要权限,直接放行
  }
})

这样,所有配置了 meta: { requiresAuth: true } 的路由,都会被拦截验权。

路由独享守卫:beforeEnter

给单个路由加守卫,只控制这一个路由:

const routes = [
  {
    path: '/admin',
    component: Admin,
    meta: { requiresAuth: true },
    beforeEnter: (to, from, next) => {
      // 逻辑和全局守卫类似,只作用于这个路由
      if (isLogin()) {
        next()
      } else {
        next('/login')
      }
    }
  }
]

权限控制思路:给需要权限的路由加 meta.requiresAuth = true,然后用全局守卫统一拦截,判断用户登录状态,没登录就跳登录页,这样一套下来,就能实现“未登录用户进不去后台页面”的效果。

开发时遇到“路由跳转后页面不更新”咋解决?

这问题特常见,原因是路由参数变了,但组件被复用了——比如从 /user/1 跳到 /user/2,Vue 为了性能,会复用同一个 User 组件实例,导致 createdmounted 这些生命周期钩子不重新执行,数据也就不更新。

解决方法有三种,按需选:

方法 1:监听 $route 变化

在组件里用 watch 监听 $route 的变化,参数变了就重新请求数据:

export default {
  watch: {
    $route(to, from) {
      // to 是新路由,from 是旧路由
      this.fetchUserData(to.params.id) // 重新调接口拿新数据
    }
  },
  methods: {
    fetchUserData(id) { ... }
  }
}

方法 2:给 <router-view> 加 key

在父组件的 <router-view> 上加 key,值设为 $route.fullPath(完整 URL),这样 URL 变了,key 也变,Vue 会认为组件需要重新渲染:

<router-view :key="$route.fullPath"></router-view>

方法 3:用组件内守卫 beforeRouteUpdate

在组件里写 beforeRouteUpdate 守卫,参数变化时执行逻辑:

export default {
  beforeRouteUpdate(to, from, next) {
    // 路由更新前,拿到新参数
    this.userId = to.params.id
    this.fetchUserData(this.userId)
    next() // 必须调用 next 放行
  }
}

这三种方法都能解决“组件复用导致数据不更新”的问题,选哪种看项目习惯,监听 $route

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门