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

Vue Router 指南入门到实战,这些问题你搞懂了吗?

terry 20小时前 阅读数 15 #Vue
文章标签 Vue Router;实战

前端项目里用 Vue 开发单页应用(SPA),页面跳转、组件切换这些需求咋实现?Vue Router 作为官方路由工具,能帮我们搞定路由管理,但新手刚接触时总会遇到一堆问题:咋配置?动态路由咋用?路由守卫有啥用?今天就用问答形式,把 Vue Router 从入门到实战的关键问题一次讲清楚~

Vue Router 是什么,能解决项目里哪些问题?

Vue Router 是 Vue 官方的路由管理器,专门给单页应用(SPA)做“页面导航”,SPA 最大特点是整个项目只有一个 HTML 文件,页面切换靠组件渲染实现,这时候就得靠路由来控制“哪个路径显示哪个组件”。

它能解决的核心问题不少:

  • URL 和组件的映射:比如访问 /home 显示 Home 组件,/about 显示 About 组件;
  • 页面跳转无刷新:SPA 跳转不用像多页应用那样整页刷新,路由能让组件切换更丝滑;
  • 嵌套视图管理:像后台系统的“侧边栏 + 内容区”结构,子路由能嵌套在父路由里;
  • 权限控制:比如某些页面必须登录才能进,路由守卫能拦截验证;
  • URL 参数处理:动态路由(如 /user/123)能传递参数,实现“用户 ID 不同,页面数据不同”。

举个🌰:做电商 App 时,商品列表页点“商品卡片”跳转到详情页,路由就能让 /product/1001 对应 ProductDetail 组件,还能把 1001 当参数传给组件,加载对应商品数据。

怎么给 Vue 项目配置 Vue Router?

配置分安装 → 建路由文件 → 写规则 → 挂载到 Vue 实例这几步,以 Vue 2 + Vue Router 3.x 为例(Vue 3 版本后面单独讲):

  1. 安装依赖:打开终端,项目根目录执行 npm install vue-router@3(Vue 2 对应 3.x 版本,Vue 3 用 4.x);

  2. 创建路由文件:在 src 下新建 router/index.js,用来写路由规则;

  3. 定义路由规则:在 index.js 里引入 Vue、VueRouter 和组件,然后配置 routes 数组。

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    import Home from '../views/Home.vue'
    import About from '../views/About.vue'
    Vue.use(VueRouter) // 注册路由插件
    const routes = [
      {
        path: '/', // 路径
        name: 'Home', // 路由名(可选)
        component: Home // 对应的组件
      },
      {
        path: '/about',
        name: 'About',
        component: About
      }
    ]
    const router = new VueRouter({
      routes // 传入规则
    })
    export default router
  4. 挂载到根 Vue 实例:打开 src/main.js,引入 router 并挂载:

    import Vue from 'vue'
    import App from './App.vue'
    import router from './router' // 引入路由实例
    new Vue({
      router, // 挂载到Vue实例
      render: h => h(App)
    }).$mount('#app')

在 App.vue 里加 <router-view></router-view>,这个标签是“路由出口”——匹配到的组件会渲染到这里。

<template>
  <div id="app">
    <router-view></router-view> <!-- 组件渲染到这 -->
  </div>
</template>

动态路由参数怎么用,开发中哪些场景会用到?

动态路由就是路径里带可变参数,格式是 /路径/:参数名/user/:id 里的 :id 就是参数,组件里可以通过 $route.params.id 拿到这个参数。

场景特别多:用户个人页(不同用户 ID 对应不同页面)、商品详情页(不同商品 ID 加载不同数据)、文章详情页(不同文章 ID 渲染不同内容)…

举个实际开发的🌰:

  1. 先配置动态路由规则:
    const routes = [
      {
        path: '/user/:id', // :id 是动态参数
        component: User
      }
    ]
  2. 在 User 组件里获取参数:可以用 $route.params.id,比如在 created 钩子发请求:
    export default {
      created() {
        const userId = this.$route.params.id // 拿到动态参数
        this.fetchUserInfo(userId) // 调接口拿用户数据
      },
      methods: {
        fetchUserInfo(id) {
          // 发请求逻辑...
        }
      }
    }
  3. 注意:如果路由参数变化,但组件没销毁(比如从 /user/1 跳到 /user/2),组件的 created 不会重新执行,这时候得用 watch 监听 $route 变化:
    watch: {
      '$route'(to, from) {
        const newId = to.params.id
        this.fetchUserInfo(newId)
      }
    }

嵌套路由在实际开发中咋玩?为啥要用嵌套?

嵌套路由就是“路由里套路由”,对应页面的嵌套结构,比如后台管理系统常见的布局:顶部导航栏 + 左侧侧边栏 + 右侧内容区,右侧内容区”要根据侧边栏点击显示不同子页面(如首页、订单页、设置页),这时候就需要嵌套路由。

实现步骤分两步:父路由配置 children 数组 + 父组件里放 <router-view>

举个后台系统的🌰:

  1. 配置嵌套路由规则:父路由是 /dashboard,子路由是 /dashboard/home/dashboard/profile
    const routes = [
      {
        path: '/dashboard',
        component: Dashboard, // 父组件
        children: [ // 子路由数组
          {
            path: 'home', // 注意:路径不用加 / ,会自动拼接成 /dashboard/home
            component: DashboardHome
          },
          {
            path: 'profile',
            component: DashboardProfile
          }
        ]
      }
    ]
  2. 在父组件 Dashboard.vue 里加 <router-view>,子组件会渲染到这里:
    <template>
      <div class="dashboard">
        <div class="sidebar">侧边栏</div>
        <div class="content">
          <router-view></router-view> <!-- 子组件渲染到这 -->
        </div>
      </div>
    </template>

这样,访问 /dashboard/home 时,Dashboard 组件先渲染,它的 <router-view> 再渲染 DashboardHome 组件,实现“父 - 子”结构的嵌套。

编程式导航和声明式导航有啥区别,啥时候用?

Vue Router 里有两种跳转方式:声明式(<router-link>)编程式(this.$router.push 等方法),核心区别是“在哪写跳转逻辑”。

  • 声明式:用 <router-link to="路径"> 标签实现跳转,适合模板里的导航(比如菜单、导航栏),优点是不用写 JS 代码,Vue Router 会自动处理点击事件和路由跳转,例子:
    <router-link to="/about">关于我们</router-link>
  • 编程式:用 this.$router.push('路径')this.$router.replace('路径') 等方法,适合逻辑里的跳转(比如按钮点击后判断权限再跳转、表单提交成功后跳转),例子:
    <button @click="goAbout">跳转到关于页</button>
    <script>
    export default {
      methods: {
        goAbout() {
          // 可以加逻辑判断,比如是否登录
          this.$router.push('/about')
        }
      }
    }
    </script>

模板里的跳转优先用声明式(简洁),JS 逻辑里的跳转用编程式(灵活)。

路由守卫怎么理解,项目里怎么用?

路由守卫就是路由导航过程中的“钩子函数”,能在“路由跳转前、跳转后、进入组件前”等时机执行代码,用来做权限验证、数据预加载、修改页面标题这些事。

路由守卫分三类:全局守卫(整个路由系统生效)、路由独享守卫(单个路由生效)、组件内守卫(组件内部生效)。

(1)全局守卫:router.beforeEach

在路由实例里配置,每次路由跳转前都会触发,最典型的场景是登录权限验证:比如某些页面必须登录才能进,没登录就跳转到登录页。

// router/index.js
router.beforeEach((to, from, next) => {
  // to: 要跳转到的目标路由
  // from: 从哪个路由跳过来
  // next: 必须调用的函数,决定是否跳转
  const isLogin = localStorage.getItem('token') // 假设用token判断登录
  if (to.meta.requiresAuth && !isLogin) {
    next('/login') // 没登录且需要权限,跳转到登录页
  } else {
    next() // 放行
  }
})

上面代码里的 to.meta.requiresAuth 是路由的“元信息”(后面问题会讲),用来标记该路由是否需要权限。

(2)路由独享守卫:beforeEnter

直接写在单个路由规则里,只有进入这个路由时才触发,比如某个路由需要验证参数是否合法:

const routes = [
  {
    path: '/order/:id',
    component: Order,
    beforeEnter: (to, from, next) => {
      const orderId = to.params.id
      if (/^\d+$/.test(orderId)) { // 验证id是否是数字
        next()
      } else {
        next('/404') // 不合法跳转到404
      }
    }
  }
]

(3)组件内守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

写在组件内部,控制组件和路由的交互。beforeRouteEnter 在进入组件前触发(此时组件实例还没创建,不能用 this),适合预加载数据beforeRouteLeave 在离开组件前触发,适合拦截(比如表单没保存不让走)

export default {
  // 进入组件前触发,此时this还不存在,用next传参
  beforeRouteEnter(to, from, next) {
    fetchData().then(data => {
      next(vm => { // vm是组件实例
        vm.data = data // 把数据传给组件
      })
    })
  },
  // 路由参数变化时触发(比如从 /user/1 到 /user/2)
  beforeRouteUpdate(to, from, next) {
    this.userId = to.params.id
    this.fetchUserInfo(this.userId)
    next()
  },
  // 离开组件前触发,可拦截
  beforeRouteLeave(to, from, next) {
    if (this.formDirty) { // 假设表单有未保存内容
      if (window.confirm('表单没保存,确定离开?')) {
        next()
      } else {
        next(false) // 取消跳转
      }
    } else {
      next()
    }
  }
}

Hash 模式和 History 模式选哪个,有啥坑?

Vue Router 有两种路由模式,决定 URL 的表现形式和底层原理:

(1)Hash 模式(默认)

URL 里带 (http://xxx.com/#/home),它基于URL 哈希值(#后面的部分)变化实现路由,优点是兼容性好(老浏览器也支持),不用后端配置;缺点是 URL 不太美观,有个 。

(2)History 模式

URL 是正常格式(http://xxx.com/home),基于 HTML5 的 History APIpushStatereplaceState)实现,优点是 URL 更“友好”,用户体验好;缺点是需要后端配合,否则刷新页面会 404。

选哪个? 如果项目对 URL 美观度要求高(比如官网、营销页),选 History 模式,但要处理后端配置;如果是内部系统、对兼容性要求高,选 Hash 模式更省心。

History 模式的坑:部署到服务器后,直接刷新 http://xxx.com/home 会报 404,因为服务器没找到对应的资源,解决方法是让服务器把所有路由请求都指向 index.html(前端路由接管),Nginx 配置:

location / {
  try_files $uri $uri/ /index.html;
}

这样,不管用户访问哪个路径,服务器都会返回 index.html,由前端路由来匹配组件。

路由懒加载怎么配置,对性能有啥帮助?

路由懒加载是把每个路由对应的组件打包成单独的小文件(chunk),页面初始加载时只加载首页组件,其他路由组件等用户访问时再加载,这能减少首屏加载时间,提升性能。

配置很简单:把路由的 component 改成动态 import 形式(() => import('组件路径'))。

举个🌰:普通导入 vs 懒加载导入:

// 普通导入(首屏会加载Home和About组件)
import Home from '../views/Home.vue'
import About from '../views/About.vue'
// 懒加载导入(首屏只加载Home,About等访问时再加载)
const Home = () => import('../views/Home.vue')
const About = () => import('../views/About.vue')
const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About }
]

这样配置后,Webpack 会自动把每个 import() 对应的组件打成单独的 chunk,浏览器在需要时才加载,首屏 bundle 体积变小,加载更快,用户打开页面时等待时间更短。

多路由出口(命名视图)怎么用,适合哪些场景?

默认情况下,一个页面只有一个 <router-view>(路由出口),但有时候页面需要同时渲染多个组件(比如头部、侧边栏、主体分别由不同组件组成),这时候就得用命名视图——给 <router-view>name 属性,路由配置里用 components 对应多个组件。

场景:复杂布局页,比如后台管理系统的布局组件,需要同时渲染 Header、Sidebar、Main 三个组件。

实现步骤:

  1. 在模板里给 <router-view>name
    <template>
      <div class="layout">
        <router-view name="header"></router-view> <!-- 命名为header -->
        <div class="content">
          <router-view name="sidebar"></router-view> <!-- 命名为sidebar -->
          <router-view></router-view> <!-- 默认name是default -->
        </div>
      </div>
    </template>
  2. 路由配置里用 components 对应多个组件:
    const routes = [
      {
        path: '/',
        components: {
          default: Main, // 对应默认name的router-view
          header: Header, // 对应name="header"的router-view
          sidebar: Sidebar // 对应name="sidebar"的router-view
        }
      }
    ]

这样,访问 时,三个 <router-view> 会分别渲染 Main、Header、Sidebar 组件,实现多区域同时渲染。

路由元信息(meta)有啥实际作用,怎么用?

路由元信息是给每个路由配置

版权声明

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

发表评论:

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

热门