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

Vue Router 是啥?单页应用为啥离不开它?

terry 3小时前 阅读数 7 #Vue

做单页应用开发时,路由管理总让人头大?页面跳转逻辑乱、权限控制难、动态页面适配差……Vue Router 作为 Vue 生态里专门管路由的工具,能帮我们把这些难题逐个击破,这篇文章用问答形式,把 Vue Router 从基础到实战的知识点拆明白,新手也能跟着理清思路~

单页应用(SPA)的核心是**只加载一次页面,后续“切换页面”靠 JavaScript 动态渲染组件**,但用户体验得像多页应用一样流畅(比如刷新、前进后退正常),Vue Router 干的事,*把 URL 变化和组件渲染做精准映射**——让 URL 变了,页面组件也跟着换,同时还能管理页面状态、历史记录这些细节。

举个例子:做个博客 SPA,点击“关于我”时,URL 从 变成 /about,页面自动渲染 About 组件,要是没路由,要么页面刷新体验差,要么得自己写一堆逻辑监听 URL、手动切换组件,麻烦到哭,对比多页应用(每次跳转都刷新整页),SPA 靠路由实现“单页内的多视图切换”,既保流畅性又省资源,而 Vue Router 就是这套逻辑的“指挥官”。

从零开始,怎么给 Vue 项目配好路由?

想让路由跑起来,分安装、配规则、挂到根实例三步:

第一步:装依赖

打开终端,在 Vue 项目里执行 npm install vue-router(如果用 Vue CLI 初始化项目时选了“路由”,这步会自动完成)。

第二步:写路由规则

新建 router/index.js 文件,导入 Vue、VueRouter 和要映射的组件,再定义路由规则:

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/components/Home.vue'   // 导入首页组件
import About from '@/components/About.vue' // 导入关于页组件
Vue.use(VueRouter) // 注册路由插件,让 Vue 能识别路由相关语法
// 定义路由规则:path 是 URL 路径,component 是对应组件
const routes = [
  { path: '/', component: Home },     
  { path: '/about', component: About }
]
// 创建路由实例,把规则传进去
const router = new VueRouter({ routes })
export default router // 导出路由实例,给 main.js 用

第三步:挂到 Vue 根实例

打开 main.js,把路由实例注入 Vue 根实例,让所有组件都能访问路由功能:

import Vue from 'vue'
import App from './App.vue'
import router from './router' // 导入上面写的路由配置
new Vue({
  router, // 把路由实例注入,所有组件可通过 this.$router 调用路由方法
  render: h => h(App)
}).$mount('#app')

App.vue 里加 <router-view></router-view>(这是“路由出口”,匹配的组件会渲染到这里),再用 <router-link to="/">首页</router-link> 这类标签做导航,一个基础路由就跑通啦~

页面跳转有门道,声明式和编程式导航咋选?

页面跳转分声明式(用 编程式(用 this.$router 方法),场景不同用法不同:

声明式导航:适合模板里的“静态导航”

在模板里写导航时,用 <router-link> 最方便,比如导航栏、菜单:

<router-link to="/">首页</router-link>
<router-link to="/about">lt;/router-link>

Vue 会把它渲染成 <a> 标签,点击自动跳转,还能自动加“激活样式”(配了 activeClass 的话),不用自己写点击事件。

编程式导航:适合逻辑里的“动态跳转”

在 JavaScript 逻辑里跳转(比如按钮点击后判断权限再跳),用 this.$router 的方法,最常用的是 push

methods: {
  submitForm() {
    // 假设表单验证通过,跳转到结果页
    this.$router.push('/success') 
  }
}

除了 push,还有 replace(替换当前历史记录,后退时回不去)、go(类似 history.go,控制前进/后退步数)。

简单说:模板里的导航用声明式,逻辑里的跳转用编程式,各司其职更清爽~

动态路由、嵌套路由,复杂页面咋拆分?

实际项目里,页面不可能只有平级的“首页/关于页”,还得处理动态页面(如商品详情)多层嵌套(如后台管理页的子页面)

动态路由:复用组件,按参数变内容

比如电商 App 的商品详情页,每个商品 URL 是 /product/123/product/456,但都用同一个 Product 组件,这时用动态段(:id)配路由:

{ path: '/product/:id', component: Product }

组件里通过 this.$route.params.id 拿到当前商品 ID,再发请求拿对应数据,这样不用给每个商品写新路由,一个组件复用到底,省代码又好维护。

嵌套路由:拆分多层页面结构

比如后台管理页面 /dashboard,点侧边栏“订单”跳 /dashboard/order,点“分析”跳 /dashboard/analysis,这种“父页面套子页面”的结构,用嵌套路由

{ 
  path: '/dashboard', 
  component: Dashboard, // 父组件
  children: [ // 子路由数组
    { path: 'order', component: Order }, 
    { path: 'analysis', component: Analysis }
  ] 
}

父组件 Dashboard.vue 里得放 <router-view></router-view>,子路由匹配的组件(Order、Analysis)会渲染到这里,这样页面结构分层清晰,和组件化思想一脉相承~

路由守卫是干啥的?权限控制、页面拦截全靠它?

路由守卫像“路由的门卫”,在路由跳转前、后做事情(比如权限验证、数据预加载、页面拦截),它分三类:全局守卫(管整个应用的路由)、路由独享守卫(只管某个路由)、组件内守卫(组件自己生命周期里管)。

全局守卫:router.beforeEach

最常用的是全局前置守卫 beforeEach,跳转前触发,比如判断用户是否登录,没登录就拦截到登录页:

router.beforeEach((to, from, next) => {
  // to: 要跳去的路由;from: 从哪个路由来;next: 放行/跳转的函数
  const isLogin = localStorage.getItem('token') // 假设用 token 判断登录
  if (to.path === '/login') { 
    next() // 去登录页,直接放行
  } else {
    isLogin ? next() : next('/login') // 没登录就跳登录页
  }
})

还有全局后置守卫 afterEach,跳转后触发,适合改页面标题、埋点统计。

路由独享守卫:beforeEnter

给单个路由配守卫,比如某个敏感页面,除全局验证外还要额外检查:

{ 
  path: '/secret', 
  component: Secret, 
  beforeEnter: (to, from, next) => {
    // 这里写针对 /secret 的权限逻辑
    const hasPermission = checkPermission() 
    hasPermission ? next() : next('/403')
  }
}

组件内守卫:beforeRouteEnter 等

组件里的守卫,比如进入组件前加载数据:

export default {
  beforeRouteEnter(to, from, next) {
    // 这里还拿不到 this(组件实例没创建),发请求放 next 里
    axios.get('/data').then(res => {
      next(vm => { // vm 是组件实例
        vm.data = res.data 
      })
    })
  },
  beforeRouteUpdate(to, from, next) {
    // 路由参数变了,但组件复用(如动态路由 /product/:id 从 123 变 456)
    this.fetchData(to.params.id) 
    next()
  }
}

组件内守卫能精细控制组件和路由的交互,处理数据加载、参数变化很方便~

开发时碰到路由 bug,常见坑咋避?

路由用顺了也会遇“玄学问题”,提前避坑省头发:

坑 1:history 模式下刷新页面 404

Vue Router 有 hash(URL 带 #,如 xxx.com/#/about)和 history(URL 干净,如 xxx.com/about)两种模式,用 history 时,服务器得配置 fallback(所有请求落到 index.html),否则用户刷新会因服务器找不到 /about 返回 404。

解决:nginx 加 try_files $uri $uri/ /index.html;,或结合 Vue CLI 的 publicPath 配服务器规则,确保请求都指向 index.html。

坑 2:动态路由参数变了,组件不刷新

比如从 /product/123/product/456,因组件复用(同个 Product 组件),Vue 不销毁重建,生命周期钩子(如 created)不执行,数据不更新。

解决:用 watch $routebeforeRouteUpdate 监听参数变化,重新拉数据:

watch: {
  '$route' (to) {
    this.fetchData(to.params.id)
  }
}
// 或用 beforeRouteUpdate
beforeRouteUpdate(to, from, next) {
  this.fetchData(to.params.id)
  next()
}

坑 3: 激活样式不生效

想让当前路由的 高亮,配了 activeClass 却没效果?可能是路由匹配太“松”。 会匹配所有以 开头的路由(/about、/product 等),导致首页 link 一直激活。

解决:加 exact 属性开精确匹配

<router-link to="/" exact>首页</router-link>

这样只有 URL 完全等于 时才激活~

实战案例:用 Vue Router 搭个简易博客 SPA

光看理论不够,动手做个小项目更扎实,需求:做个博客,有首页(列表)、文章详情页、分类页,还要用路由守卫做权限控制(假设“草稿文章”需登录才能看)。

步骤 1:项目初始化 + 装路由

用 Vue CLI 新建项目,选上 Vue Router,结构里 router/index.js 配路由,views 文件夹放页面级组件(Home、Post、Category)。

步骤 2:配路由规则

const routes = [
  { path: '/', component: Home },
  { 
    path: '/post/:id', 
    component: Post, 
    beforeEnter: (to, from, next) => { // 路由独享守卫,判断是否草稿
      const post = getPostById(to.params.id) // 假设拿文章数据的函数
      if (post.isDraft && !isLogin()) { 
        next('/login') // 草稿且没登录,跳登录
      } else {
        next()
      }
    }
  },
  { path: '/category/:name', component: Category },
  { path: '/login', component: Login }
]

步骤 3:写组件逻辑

  • Home.vue:用假数据渲染文章列表,每个文章项用 <router-link :to="'/post/'+post.id"> 跳详情页。
  • Post.vue:通过 this.$route.params.id 拿文章 ID,发请求(或读假数据)渲染内容。
  • Category.vue:通过 this.$route.params.name 拿分类名,渲染对应文章列表。

步骤 4:加全局守卫控制登录

router/index.js 里加全局前置守卫,判断非登录页且没 token 时跳登录:

router.beforeEach((to, from, next) => {
  const isLogin = localStorage.getItem('token')
  if (to.path !== '/login' && !isLogin) {
    next('/login')
  } else {
    next()
  }
})

步骤 5:测试流程

  • 访问首页,点文章跳详情:草稿文章会被拦截到登录页,登录后(存 token 到 localStorage)再跳回去能看。
  • 点分类,URL 变 /category/前端,页面渲染前端分类文章。
  • 登录页输账号密码(模拟存 token),跳转后能正常访问受限页面。

这个小项目把路由配置、动态路由、守卫、导航方式全练了一遍,做完对 Vue Router 就有数啦~

Vue Router 是 SPA 开发的“导航中枢”,从基础配置到复杂场景,掌握路由映射、导航方式、守卫机制这些点,能让单页应用的页面管理更丝滑,多练案例、踩踩坑,遇到问题翻翻官方文档(Vue Router 文档讲得超细!),自然就熟了~下次做 SPA 时,路由这块心里就有底啦~

版权声明

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

发表评论:

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

热门