【Vue学习笔记】路由详解
@TOC
一、什么是路由?
在Vue中,路由是指通过URL路径来管理不同页面之间的交互跳转和状态切换的机制。Vue Router是Vue.js官方提供的路由管理器,可以用于构建单页应用(SPA)。
通过Vue Router,开发者可以定义多个路由规则,每个规则对应一个路径,访问该路径时就会渲染对应的组件。同时,Vue Router还支持动态路由、嵌套路由、命名路由、路由传参等功能,方便开发者根据实际需求进行配置和使用。
在Vue中使用路由需要先安装Vue Router,并在Vue实例中注册路由器。然后,就可以使用<router-link>
组件创建链接,以及使用<router-view>
组件显示当前路由匹配到的组件。
二、创建路由
在Vue中创建路由需要使用Vue Router,以下是创建路由的基本步骤:
安装Vue Router:
npm install vue-router
在main.js中导入Vue Router并注册:
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App.vue'
Vue.use(VueRouter)
const router = new VueRouter({
routes: [
{
path: '/home',
component: Home
},
{
path: '/about',
component: About
}
]
})
new Vue({
router,
render: h => h(App),
}).$mount('#app')
在组件中使用<router-link>
和<router-view>
:
<template>
<div>
<router-link to="/home">Home</router-link>
<router-link to="/about">About</router-link>
<router-view></router-view>
</div>
</template>
其中,routes属性定义了一个包含多个路由规则的数组。每个路由规则都包含两个属性:path表示路径,component表示对应的组件。
在Vue实例中通过router属性注入路由器,然后在模板中使用<router-link>
组件来创建链接,使用<router-view>
组件来显示当前路由匹配到的组件。
三、路由导航
在Vue中,路由导航可以通过编程式导航和声明式导航两种方式实现。
声明式导航
声明式导航是利用<router-link>
组件来创建链接,实现路由导航。例如:
<template>
<div>
<router-link to="/home">Home</router-link>
<router-link to="/about">About</router-link>
</div>
</template>
编程式导航
编程式导航是通过调用Router实例的方法,例如push、replace等来实现路由导航。例如:
// 在组件中使用$router对象
this.$router.push('/home')
this.$router.replace('/about')
// 在非组件中使用$router对象
import router from './router'
router.push('/home')
router.replace('/about')
可以看到,编程式导航需要先获取Router实例,然后通过实例调用相应的方法实现导航。
注意:在使用导航方法时,必须保证当前页面已经存在Router实例。通常情况下,在Vue组件中可以通过this.$router访问Router实例,而在非组件中需要先导入并创建一个Router实例。
四、路由重定向和404页面
在Vue中,可以通过路由重定向和404页面来处理路由跳转异常的情况。
路由重定向
路由重定向是指在访问某个路径时,自动跳转到另一个路径。例如:
const router = new VueRouter({
routes: [
{
path: '/',
redirect: '/home'
},
{
path: '/home',
component: Home
}
]
})
在上面的例子中,当访问根路径时会自动重定向到/home路径。可以看到,通过在路由规则中添加redirect属性来实现路由重定向。
404页面
404页面是指在访问不存在的路径时显示的页面,通常用于提示用户当前页面不存在等信息。可以通过创建一个专门的路由规则来实现404页面。例如:
const router = new VueRouter({
routes: [
{
path: '/home',
component: Home
},
{
path: '*',
component: NotFound
}
]
})
在上面的例子中,使用通配符匹配所有不存在的路径,并将其导航到NotFound组件。可以看到,通过在路由规则中添加path为的规则来实现404页面。
需要注意的是,路由重定向和404页面都只能匹配一次,即只有第一个匹配的规则会被执行。因此,在定义路由规则时需要注意规则的顺序。
五、多级路由
在Vue中,多级路由指的是一个路由可以拥有多个子路由,这些子路由可以有不同的路径和组件。多级路由可以用于构建复杂的应用程序页面结构,使得页面的层次感更加明显。
在Vue中,使用Vue Router来实现多级路由。一个多级路由通常由一个父级路由和若干个子级路由组成。父级路由的组件模板中通常包含一个或多个<router-view>
标签,用于显示匹配当前路径的子路由组件。
在Vue中创建多级路由的步骤如下:
1.在router/index.js
文件中,使用Vue Router
创建路由实例,并定义路由路径和组件。
2.在父级路由组件的模板中,使用<router-view>
标签来占位子路由组件。
3.定义子级路由,包括其路径和组件。
4.在父级路由的组件逻辑中,使用children
属性将子路由添加到该路由下。
例如,以下是一个Vue多级路由的示例代码:
// router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/views/Home.vue'
import Parent from '@/views/Parent.vue'
import Child from '@/views/Child.vue'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/parent',
name: 'parent',
component: Parent,
children: [
{
path: 'child',
name: 'child',
component: Child
}
]
}
]
})
<!-- Parent.vue -->
<template>
<div>
<h1>Parent Component</h1>
<router-view></router-view>
</div>
</template>
<!-- Child.vue -->
<template>
<div>
<h1>Child Component</h1>
</div>
</template>
在上面的示例中,/parent
是父级路由路径,Parent.vue
是父级路由组件。/parent/child
是子级路由路径,Child.vue
是子级路由组件。在父级路由组件的模板中,使用了<router-view>
标签来占位子路由组件。
需要注意的是,在定义子级路由时,其路径应该是相对于父级路由路径的。例如,在上面的示例中,子级路由的路径为child
,而不是/parent/child
。
六、动态路由匹配/路由传参
在Vue中,可以使用动态路由匹配和路由传参来实现根据不同的参数值展示不同的页面内容。
Vue中路由传参的两种方式是:
1.通过路由配置中的params
这种方式传递的参数会被编码到URL中,可以在$route.params中获取。
示例代码:
const router = new VueRouter({
routes: [
{
path: '/user/:id',
name: 'user',
component: User
}
]
})
// 通过路由跳转传递参数
router.push({ name: 'user', params: { id: 123 }})
在User组件中获取参数:
export default {
name: 'User',
mounted() {
console.log(this.$route.params.id) // 输出123
}
}
2.通过路由配置中的query
这种方式传递的参数会被编码到URL中,可以在$route.query中获取。
示例代码:
const router = new VueRouter({
routes: [
{
path: '/user',
name: 'user',
component: User
}
]
})
// 通过路由跳转传递参数
router.push({ name: 'user', query: { id: 123 }})
在User组件中获取参数:
export default {
name: 'User',
mounted() {
console.log(this.$route.query.id) // 输出123
}
}
区别:
params传递的参数会被编码到URL中,而query传递的参数则不会。params传递的参数更适用于需要在URL中体现参数的场景,而query则更适用于无需在URL中体现参数的场景。另外,params传递的参数可以设置类型校验,而query则不能。
七、路由模式
Vue中的路由模式分为两种:history模式和hash模式。
history模式
history模式使用HTML5的history API来管理路由状态,通过修改浏览器的URL地址来实现页面的跳转和前进后退。在history模式下,URL中不会出现#符号。
示例代码:
const router = new VueRouter({
mode: 'history',
routes: [...]
})
hash模式
hash模式使用URL中的hash值来模拟路由状态,通过监听hashchange事件来实现页面的跳转和前进后退。在hash模式下,URL中会出现#符号。
示例代码:
const router = new VueRouter({
mode: 'hash',
routes: [...]
})
两种模式的区别:
- URL中是否出现#符号。hash模式url有#号,history模式url没有#号。
- history模式需要服务器端的支持,因为在history模式下,浏览器向服务器发送请求时会将当前URL发送给服务器,而服务器需要返回正确的页面内容。而hash模式则不需要服务器端的支持,因为hash值不会被发送给服务器。
- history模式可以使用HTML5的historyAPI来管理路由状态,功能更强大,但对浏览器的要求更高;而hash模式则比较简单,兼容性较好,但功能相对较弱。
- history模式需要特殊的配置来支持SPA应用的刷新,而hash模式则不需要。
八、路由守卫/导航守卫/路由钩子/路由卫士
Vue中的路由守卫可以通过在路由配置中定义一些钩子函数来实现,用于在路由跳转时对路由进行拦截或者进行某些操作。
Vue中的路由守卫主要分为全局守卫和组件内守卫两种。
全局守卫
全局守卫是应用于所有路由的守卫,包括:
beforeEach(to, from, next):在路由跳转之前触发,to表示要跳转到的路由对象,from表示当前的路由对象,next是一个函数,用于控制路由跳转的行为。
afterEach(to, from):在路由跳转之后触发,to表示要跳转到的路由对象,from表示当前的路由对象。
示例代码:
const router = new VueRouter({
routes: [...]
})
router.beforeEach((to, from, next) => {
// 对路由进行拦截或者进行某些操作
next() // 执行下一个路由
})
router.afterEach((to, from) => {
// 在路由跳转之后进行某些操作
})
组件内守卫
组件内守卫是应用于某个具体组件的路由守卫,包括:
beforeRouteEnter(to, from, next):在进入路由对应的组件之前触发,to表示要跳转到的路由对象,from表示当前的路由对象,next是一个函数,用于控制路由跳转的行为,但在此时无法直接访问组件实例。
beforeRouteUpdate(to, from, next):在当前路由对应的组件复用时触发,to表示要跳转到的路由对象,from表示当前的路由对象,next是一个函数,用于控制路由跳转的行为。
beforeRouteLeave(to, from, next):在离开当前路由对应的组件时触发,to表示要跳转到的路由对象,from表示当前的路由对象,next是一个函数,用于控制路由跳转的行为。
示例代码:
export default {
beforeRouteEnter(to, from, next) {
// 在进入路由对应的组件之前进行某些操作
next()
},
beforeRouteUpdate(to, from, next) {
// 在当前路由对应的组件复用时进行某些操作
next()
},
beforeRouteLeave(to, from, next) {
// 在离开当前路由对应的组件时进行某些操作
next()
}
}
路由守卫的作用:
对路由进行拦截,比如检查用户是否已登录,如果未登录则跳转到登录页面。
在路由跳转之前或之后进行某些操作,比如记录日志、修改页面标题等。
在进入或离开某个具体组件时进行某些操作,比如获取组件数据、清除组件数据等。
九、路由懒加载
使用传统路由的写法 再引用组件的时候 第一次会把项目下的所有页面全部都引用一次 可能用户的设备较慢 导致首次加载页面白屏 用户体验不好 为了解决这个问题我们可以使用路由懒加载的方式按需加载我们的路由页面 用到哪个加载哪个。
Vue中路由懒加载指的是在路由被访问时才加载对应的组件,而不是一开始就把所有组件都加载进来。
使用路由懒加载可以有效减少应用的初始加载时间,提高应用的性能和用户体验。
Vue中实现路由懒加载的方式有以下几种:
使用函数式组件
使用函数式组件可以通过import()动态加载组件。
示例代码:
const Home = () => import('./views/Home.vue')
const router = new VueRouter({
routes: [
{
path: '/home',
name: 'home',
component: Home
}
]
})
使用异步组件
异步组件使用Vue的异步组件特性来实现动态加载组件。
示例代码:
const Home = resolve => {
require.ensure(['./views/Home.vue'], () => {
resolve(require('./views/Home.vue'))
})
}
const router = new VueRouter({
routes: [
{
path: '/home',
name: 'home',
component: Home
}
]
})
使用webpack的require.ensure()
使用webpack的require.ensure()方法可以实现在路由被访问时才加载对应的组件。
示例代码:
const router = new VueRouter({
routes: [
{
path: '/home',
name: 'home',
component: function (resolve) {
require.ensure(['./views/Home.vue'], function () {
resolve(require('./views/Home.vue'))
})
}
}
]
})
使用ES6的import()
使用ES6的import()语法可以动态加载组件。
示例代码:
const router = new VueRouter({
routes: [
{
path: '/home',
name: 'home',
component: () => import('./views/Home.vue')
}
]
})
使用路由懒加载需要注意以下几点:
- 只有在使用ES6的模块化语法时才能使用import()动态加载组件。
- 在使用路由懒加载时,需要将webpack的输出文件名设置为动态的,否则会出现路由切换时加载同一个组件的问题。
- 在使用路由懒加载时,需要注意组件的异步加载可能会导致组件加载顺序出现问题,需要根据实际情况进行处理。
- 路由懒加载可以在应用的初次加载时减少不必要的代码,提高应用的性能和用户体验,尤其是在应用中包含大量组件时,使用路由懒加载可以显著提高应用的加载速度。