路由基础

路由配置是 Vue Router 的核心,理解如何定义路由、映射组件,是构建单页应用的第一步。

创建路由实例

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const router = new VueRouter({
  mode: 'history',
  base: '/app',
  routes: [
    // 路由配置
  ]
})

路由配置项

path

路由路径,支持动态片段:

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

name

路由名称,用于命名路由导航:

const routes = [
  { path: '/user/:id', name: 'user', component: User }
]

<router-link :to="{ name: 'user', params: { id: 123 } }">用户</router-link>

this.$router.push({ name: 'user', params: { id: 123 } })

component

路由对应的组件:

import Home from './views/Home.vue'

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

components

命名视图,多个 router-view:

const routes = [
  {
    path: '/',
    components: {
      default: Home,
      sidebar: Sidebar,
      header: Header
    }
  }
]
<router-view></router-view>
<router-view name="sidebar"></router-view>
<router-view name="header"></router-view>

redirect

重定向:

const routes = [
  { path: '/', redirect: '/home' },
  { path: '/home', component: Home },
  { path: '/old-path', redirect: { name: 'home' } },
  { path: '/search/:q', redirect: to => {
    return { path: '/result', query: { q: to.params.q } }
  }}
]

alias

路由别名:

const routes = [
  { path: '/home', component: Home, alias: '/' },
  { path: '/user/:id', component: User, alias: '/u/:id' }
]

props

将路由参数作为组件 props:

const routes = [
  { path: '/user/:id', component: User, props: true },
  
  { path: '/search', component: Search, props: (route) => ({
    query: route.query.q
  })}
]
export default {
  props: {
    id: String
  },
  created() {
    console.log(this.id)
  }
}

meta

路由元信息:

const routes = [
  {
    path: '/admin',
    component: Admin,
    meta: {
      requiresAuth: true,
      title: '管理后台'
    }
  }
]

router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth) {
    if (!isAuthenticated()) {
      next('/login')
    } else {
      next()
    }
  } else {
    next()
  }
})

children

嵌套路由:

const routes = [
  {
    path: '/user',
    component: User,
    children: [
      {
        path: '',
        component: UserHome
      },
      {
        path: 'profile',
        component: UserProfile
      },
      {
        path: 'settings',
        component: UserSettings
      }
    ]
  }
]

beforeEnter

路由独享守卫:

const routes = [
  {
    path: '/admin',
    component: Admin,
    beforeEnter: (to, from, next) => {
      if (isAdmin()) {
        next()
      } else {
        next('/403')
      }
    }
  }
]

路由匹配

动态路径参数

const routes = [
  { path: '/user/:id', component: User }
]
export default {
  created() {
    console.log(this.$route.params.id)
  }
}

多个参数

const routes = [
  { path: '/user/:userId/post/:postId', component: Post }
]

this.$route.params.userId
this.$route.params.postId

可选参数

const routes = [
  { path: '/user/:id?', component: User }
]

正则匹配

const routes = [
  { path: '/user/:id(\\d+)', component: User },
  { path: '/:pathMatch(.*)*', component: NotFound }
]

路由匹配优先级

路由按定义顺序匹配,先定义的优先:

const routes = [
  { path: '/user/profile', component: UserProfile },
  { path: '/user/:id', component: User }
]

404 路由

捕获所有未匹配的路由:

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

history 模式:

const routes = [
  { path: '/:pathMatch(.*)*', component: NotFound }
]

路由懒加载

基本用法

const routes = [
  {
    path: '/about',
    component: () => import('./views/About.vue')
  }
]

分组打包

const routes = [
  {
    path: '/user',
    component: () => import(/* webpackChunkName: "user" */ './views/User.vue')
  },
  {
    path: '/user/profile',
    component: () => import(/* webpackChunkName: "user" */ './views/UserProfile.vue')
  }
]

获取路由信息

$route 对象

this.$route.path
this.$route.params
this.$route.query
this.$route.hash
this.$route.fullPath
this.$route.name
this.$route.meta
this.$route.matched

监听路由变化

export default {
  watch: {
    '$route'(to, from) {
      console.log('路由变化:', from.path, '->', to.path)
    }
  }
}

路由实例属性

router.app
router.mode
router.currentRoute

路由实例方法

router.push('/home')
router.push({ name: 'user', params: { id: 123 } })
router.replace('/home')
router.go(-1)
router.go(1)
router.back()
router.forward()

完整示例

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'home',
    component: () => import('./views/Home.vue'),
    meta: { title: '首页' }
  },
  {
    path: '/user/:id',
    name: 'user',
    component: () => import('./views/User.vue'),
    props: true,
    meta: { requiresAuth: true }
  },
  {
    path: '/admin',
    name: 'admin',
    component: () => import('./views/Admin.vue'),
    beforeEnter: (to, from, next) => {
      if (isAdmin()) {
        next()
      } else {
        next('/403')
      }
    }
  },
  {
    path: '*',
    name: 'not-found',
    component: () => import('./views/NotFound.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

小结

路由基础要点:

  1. 路由配置:path、name、component、meta
  2. 动态参数:id 形式的参数
  3. 重定向:redirect 和 alias
  4. 懒加载:按需加载组件
  5. 404 处理:捕获未匹配路由