Vue Routerrouting

深入LearningVue Router basicconcepts, routingconfiguration, 嵌套routing, routingparameter, 导航守卫etc. in 容

1. Vue Routeroverview

Vue Router is Vue.js官方 routingmanagement器, 它 and Vue.js core深度集成, 让构建单页面application变得易such as反掌.

1.1 Vue Router corefunctions

  • 嵌套routing/视graphmap: support many 层级 routing嵌套
  • module化 , 基于component routingconfiguration: usingcomponent来定义routing
  • routingparameter, query, 通配符: support动态routing匹配
  • 细粒度 导航控制: providing导航守卫来控制routing跳转
  • 视graph过渡效果: and Vue 过渡system无缝集成
  • 细粒度 导航控制: providing导航守卫来控制routing跳转
  • routing懒加载: supportasynchronous加载routingcomponent
  • HTML5 history模式 or hash 模式: support两种routing模式

1.2 installationVue Router

可以throughnpm or yarninstallationVue Router:

# usingnpminstallation
npm install vue-router@4

# usingyarninstallation
yarn add vue-router@4

提示

Vue Router 4 is for Vue 3 design , such as果你using is Vue 2, 应该installation Vue Router 3: npm install vue-router@3

2. basicroutingconfiguration

让我们开始creation一个basic Vue Routerapplication.

2.1 creationroutinginstance

// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import AboutView from '../views/AboutView.vue'

// 定义routing
const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/about',
    name: 'about',
    component: AboutView
  }
]

// creationroutinginstance
const router = createRouter({
  // usingHTML5history模式
  history: createWebHistory(process.env.BASE_URL),
  routes // 传入routingconfiguration
})

export default router

2.2 挂载routinginstance

// src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

const app = createApp(App)

// 挂载routinginstance
app.use(router)

app.mount('#app')

2.3 in 模板inusingrouting

in App.vueinusing<router-view>来渲染当 before routing匹配 component, using<router-link>来creation导航链接:

<!-- App.vue -->
<template>
  <div id="app">
    <nav>
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </nav>
    <router-view/>
  </div>
</template>

3. routingparameter

routingparameter允许我们 in routingin传递动态data.

3.1 动态routing匹配

// src/router/index.js
const routes = [
  // 动态routing, id is parameter
  {
    path: '/user/:id',
    name: 'user',
    component: () => import('../views/UserView.vue')
  }
]

3.2 in componentin获取routingparameter

<!-- UserView.vue -->
<template>
  <div>
    <h2>User {{ $route.params.id }}</h2>
  </div>
</template>

<script>
export default {
  name: 'UserView',
  mounted() {
    // throughthis.$route.params获取routingparameter
    console.log('User ID:', this.$route.params.id)
  },
  // 监听routingparameter变化
  watch: {
    '$route.params'(toParams, previousParams) {
      // routingparameter变化时 processing逻辑
      console.log('User ID changed from', previousParams.id, 'to', toParams.id)
    }
  }
}
</script>

3.3 可选routingparameter

可以through in parameter名 after 添加?来定义可选routingparameter:

const routes = [
  // 可选routingparameter
  {
    path: '/user/:id?',
    name: 'user',
    component: () => import('../views/UserView.vue')
  }
]

3.4 many 个routingparameter

const routes = [
  //  many 个routingparameter
  {
    path: '/user/:id/post/:postId',
    name: 'userPost',
    component: () => import('../views/UserPostView.vue')
  }
]

3.5 正则表达式routingparameter

可以using正则表达式来约束routingparameter 格式:

const routes = [
  // 只匹配numberid
  {
    path: '/user/:id(\\d+)',
    name: 'user',
    component: () => import('../views/UserView.vue')
  }
]

4. 嵌套routing

嵌套routing允许我们 in 一个component in 部嵌套另一个component, 这 for 于构建 complex 单页面application非常 has 用.

4.1 定义嵌套routing

const routes = [
  {
    path: '/user/:id',
    name: 'user',
    component: () => import('../views/UserView.vue'),
    // 嵌套routing
    children: [
      {
        // 当 /user/:id/profile 匹配成功
        path: 'profile',
        name: 'userProfile',
        component: () => import('../views/UserProfileView.vue')
      },
      {
        // 当 /user/:id/posts 匹配成功
        path: 'posts',
        name: 'userPosts',
        component: () => import('../views/UserPostsView.vue')
      }
    ]
  }
]

4.2 in 父componentin添加<router-view>

<!-- UserView.vue -->
<template>
  <div>
    <h2>User {{ $route.params.id }}</h2>
    <nav>
      <router-link :to="{ name: 'userProfile', params: { id: $route.params.id } }">Profile</router-link> |
      <router-link :to="{ name: 'userPosts', params: { id: $route.params.id } }">Posts</router-link>
    </nav>
    <!-- 嵌套routing视graph -->
    <router-view/>
  </div>
</template>

5. programming式导航

除了using<router-link>for声明式导航 out , 还可以usingrouting器 instancemethodforprogramming式导航.

5.1 basic导航method

// stringpath
this.$router.push('/about')

// object
this.$router.push({ path: '/about' })

// 命名routing (带parameter) 
this.$router.push({
  name: 'user',
  params: { id: 123 }
})

// 带queryparameter
this.$router.push({
  path: '/about',
  query: { name: 'john', age: 30 }
})

// replace当 before routing (不会留 under history记录) 
this.$router.replace('/about')

//  before 进 or  after 退
this.$router.go(1) //  before 进1步
this.$router.go(-1) //  after 退1步
this.$router.forward() //  before 进
the.$router.back() //  after 退

6. 命名routing and 命名视graph

6.1 命名routing

命名routing允许我们through名称来引用routing, 而不 is throughpath:

const routes = [
  {
    path: '/user/:id',
    name: 'user', // 命名routing
    component: () => import('../views/UserView.vue')
  }
]
// using命名routingfor导航
this.$router.push({ name: 'user', params: { id: 123 } })

//  in 模板inusing命名routing
<router-link :to="{ name: 'user', params: { id: 123 } }">User 123</router-link>

6.2 命名视graph

命名视graph允许我们 in 同一级routingin显示 many 个component:

// 定义命名视graph
const routes = [
  {
    path: '/',
    components: {
      default: HomeView,
      header: HeaderView,
      sidebar: SidebarView
    }
  }
]
<!--  in 模板inusing命名视graph -->
<template>
  <div id="app">
    <router-view name="header"/>
    <div class="main-content">
      <router-view name="sidebar"/>
      <router-view/> <!-- 默认视graph -->
    </div>
  </div>
</template>

7. routing守卫

routing守卫允许我们 in routing跳转 before after 执行一些逻辑, such asverificationuser身份, permissionchecketc..

7.1 全局守卫

全局守卫会影响所 has routing.

// 全局 before 置守卫
router.beforeEach((to, from, next) => {
  console.log('全局 before 置守卫', to, from)
  // 必须调用next()才能继续跳转
  next()
})

// 全局解析守卫
router.beforeResolve((to, from, next) => {
  console.log('全局解析守卫', to, from)
  next()
})

// 全局 after 置hook
router.afterEach((to, from) => {
  console.log('全局 after 置hook', to, from)
})

7.2 routing独享守卫

routing独享守卫只影响specific routing.

const routes = [
  {
    path: '/user/:id',
    name: 'user',
    component: () => import('../views/UserView.vue'),
    // routing独享守卫
    beforeEnter: (to, from, next) => {
      console.log('routing独享守卫', to, from)
      next()
    }
  }
]

7.3 component in 守卫

component in 守卫只影响specific component.

export default {
  name: 'UserView',
  // component in 守卫
  beforeRouteEnter(to, from, next) {
    // 进入routing before 调用, 此时componentinstance还未creation
    console.log('component in 守卫 beforeRouteEnter', to, from)
    next()
  },
  beforeRouteUpdate(to, from, next) {
    // routingupdate时调用 (such asparameter变化) 
    console.log('component in 守卫 beforeRouteUpdate', to, from)
    next()
  },
  beforeRouteLeave(to, from, next) {
    // 离开routing before 调用
    console.log('component in 守卫 beforeRouteLeave', to, from)
    next()
  }
}

7.4 导航守卫 执行顺序

  1. 触发进入otherrouting
  2. 调用全局 before 置守卫 beforeEach
  3. 调用要离开routing component in 守卫 beforeRouteLeave
  4. 调用要进入routing routing独享守卫 beforeEnter
  5. 解析asynchronousroutingcomponent
  6. 调用要进入routing component in 守卫 beforeRouteEnter
  7. 调用全局解析守卫 beforeResolve
  8. 导航completion, updateDOM
  9. 调用全局 after 置hook afterEach
  10. 触发DOMupdate
  11. 执行 beforeRouteEnter 守卫in传给 next callbackfunction

8. routing懒加载

routing懒加载允许我们 in 需要时才加载routingcomponent, from 而reducing初始加载时间, improvingapplicationperformance.

8.1 basic懒加载

const routes = [
  {
    path: '/about',
    name: 'about',
    // 懒加载routingcomponent
    component: () => import('../views/AboutView.vue')
  }
]

8.2 group懒加载

可以将 many 个routingcomponent打package to 同一个asynchronous块in:

const routes = [
  {
    path: '/about',
    name: 'about',
    // group懒加载, using相同 commentserving aschunk name
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
  },
  {
    path: '/contact',
    name: 'contact',
    // group懒加载, using相同 commentserving aschunk name
    component: () => import(/* webpackChunkName: "about" */ '../views/ContactView.vue')
  }
]

9. 404页面

可以using通配符*来匹配所 has undefined routing, from 而显示404页面:

const routes = [
  // otherrouting
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  // 404页面, 必须放 in 最 after 
  {
    path: '/:pathMatch(.*)*',
    name: 'not-found',
    component: () => import('../views/NotFoundView.vue')
  }
]

10. routing元information

routing元information允许我们 for routing添加自定义data, such as标题, permissionetc..

10.1 定义routing元information

const routes = [
  {
    path: '/about',
    name: 'about',
    component: () => import('../views/AboutView.vue'),
    // routing元information
    meta: {
      title: 'About Us',
      requiresAuth: true,
      roles: ['admin', 'user']
    }
  }
]

10.2 usingrouting元information

//  in 导航守卫inusingrouting元information
router.beforeEach((to, from, next) => {
  // 设置页面标题
  if (to.meta.title) {
    document.title = to.meta.title
  }
  
  // check is 否需要login
  if (to.meta.requiresAuth && !isLoggedIn()) {
    next({ name: 'login' })
  } else {
    next()
  }
})

//  in componentinusingrouting元information
export default {
  name: 'AboutView',
  mounted() {
    console.log('routing元information:', this.$route.meta)
  }
}

11. routing模式

Vue Routersupport两种routing模式: HTML5history模式 and hash模式.

11.1 HTML5history模式

const router = createRouter({
  // HTML5history模式
  history: createWebHistory(process.env.BASE_URL),
  routes
})

11.2 hash模式

const router = createRouter({
  // hash模式
  history: createWebHashHistory(),
  routes
})

11.3 两种模式 区别

features HTML5history模式 hash模式
URL格式 干净 URL, such as example.com/about package含#, such as example.com/#/about
serverconfiguration 需要serverconfiguration, 将所 has request重定向 to index.html 不需要serverconfiguration
浏览器support supportHTML5 History API 现代浏览器 所 has 浏览器
SEO友 good 更友 good 较差

12. best practices

12.1 routingconfigurationbest practices

  • using命名routingfor导航, 而不 is 直接usingpath
  • 将routingconfiguration拆分 for many 个file, 便于maintenance
  • usingrouting懒加载reducing初始加载时间
  • for routing添加元information, 便于统一management
  • 将404routing放 in 最 after

12.2 导航best practices

  • using<router-link>for声明式导航, using$router.push()forprogramming式导航
  • 避免using全局导航守卫processing过 many 业务逻辑
  • using导航守卫forpermissioncheck and 身份verification
  • in component in 守卫inprocessingcomponentspecific 导航逻辑

12.3 performanceoptimization

  • usingrouting懒加载
  • usinggroup懒加载, 将相关routingcomponent打package to 同一个asynchronous块in
  • 避免 in routing守卫in执行耗时operation
  • usingHTML5history模式, providing更 good user体验

练习 1: basicroutingconfiguration

  1. creation一个Vueproject, 并installationVue Router.
  2. creation三个routing: 首页, 关于页 and 联系页.
  3. in App.vuein添加导航链接 and routing视graph.
  4. testrouting跳转 is 否正常.

练习 2: 动态routing and 嵌套routing

  1. creation一个userrouting, support动态parameterid.
  2. in userrouting under creation两个嵌套routing: 个人资料 and 文章list.
  3. in usercomponentin添加嵌套routing视graph and 导航链接.
  4. test动态routing and 嵌套routing is 否正常工作.

练习 3: routing守卫 and 元information

  1. creation一个需要login才能访问 routing.
  2. for 该routing添加meta.requiresAuth: true.
  3. creation一个全局 before 置守卫, checkuser is 否login.
  4. such as果user未login, 将其重定向 to login页.
  5. testrouting守卫 is 否正常工作.