路由表的本质就是一个映射表,决定了数据包的指向
安装router
npm install vue-router@4
在src下的views中,创建 router/index.js router/Home.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/views/Home.vue'
const User = resolve => { require.ensure(['@/views/User.vue'], () => { resolve(require('@/views/User.vue')) }) };
Vue.use(VueRouter) // 导入路由对象
// 定义路由规则
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/user',
name: 'User',
// component: () => import(/* webpackChunkName: "user" */ '../views/User.vue')
component: User
}
]
// 创建路由实例
const router = new VueRouter({
mode: 'history', // vue路由只有两种模式,一种是hash,一种是history,这里使用历史模式
base: process.env.BASE_URL,
route
})
export default router
懒加载
// 方式一: 结合Vue的异步组件和Webpack的代码分析
const User = resolve => { require.ensure(['@/views/User.vue'], () => { resolve(require('@/views/User.vue')) }) };
// 方式二: AMD写法
const User = resolve => require(['@/views/User.vue'], resolve);
// 方式三: 在ES6中, 我们可以有更加简单的写法来组织Vue异步组件和Webpack的代码分割.
const Home = () => import(/* webpackChunkName: "user" */ '../views/User.vue')
路由模式
vue中的路由默认时hash模式,使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。如果不想要很丑的 hash,我们可以用路由的history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。
hash 虽然出现URL中,但不会被包含在HTTP请求中,对后端完全没有影响,因此改变hash不会重新加载页面。
history模式提供了对历史记录进行修改的功能,只是当它们执行修改是,虽然改变了当前的URL,但你浏览器不会立即向后端发送请求。history模式,会出现404 的情况,需要后台配置。
404 错误:
1、hash模式下,仅hash符号之前的内容会被包含在请求中,如 http://www.xxx.com, 因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回404错误;
2、history模式下,前端的url必须和实际向后端发起请求的url 一致,如http://www.xxx.com/book/id 。如果后端缺少对/book/id 的路由处理,将返回404错误。
路由跳转
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/user">User</router-link>
</div>
<router-view/>
或者
this.$router.push('/user')
const router = new VueRouter({
routes: [
{
path: '/user/:userId',
name: 'User', // 对路由进行命名
component: () => import(/* webpackChunkName: "user" */ '../views/User.vue')
}
]
})
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
// 以上等同于
router.push({ name: 'user', params: { userId: 123 }})
query传参
this.$router.push({name: "User", params: {userId: 123}}) // http://localhost:8081/user/123
this.$router.push({name: "User", query: {userId: 123}}) // http://localhost:8081/?userId=123
编程式导航中,使用name进行路径跳转,携带参数可以通过params和query,其中query会将参数携带在导航路径上,而使用path进行路径跳转,无法携带params,只能携带query
路由重定向
const routes = [
{
path: '/',
redirect: '/home' // 这就是路由的重定向,重新定义跳转路径
},
{
path: '/home',
component: () => import('@/views/Home.vue')
},
{
path: '/user',
component: () => import('@/views/User.vue')
},
{
path: '/detail',
component: () => import('@/views/Detail.vue')
},
{
path: '*', // 匹配所有剩余的路由,只要不是上面提及的页面,全部跳转到404页面
component: () => import('@/views/404.vue')
}
]
路由嵌套
const routes = [
{
path: '/',
// 这里可以直接使用重定向,指定到某个子路由
redirect: '/home',
component: () => import('@/views/Index.vue'),
// 使用children包裹其他组件,就可以将它们变成当前路由的子路由
children: [
{
path: '/home',
component: () => import('@/views/Home.vue')
},
{
path: '/user',
component: () => import('@/views/User.vue')
},
{
path: '/detail',
component: () => import('@/views/Detail.vue')
}
]
},
{
path: '*',
component: () => import('@/views/404.vue')
}
]
案例:用vue的嵌套路由实现一个Tab栏案例 要求页面刷新时,可以监测当前路由地址,从而切换tab栏当前项,每次页面更新,就监测路由地址,从而切换tab栏当前项,定义一个方法,专门用来判断当前路由地址
要使用Vue的嵌套路由实现一个Tab栏案例,可以按照以下步骤进行:
1.在父组件中定义需要渲染的多个子组件,并将其绑定到对应的 path 中。例如:
<template>
<div>
<router-link to="/tab/home">Home</router-link>
<router-link to="/tab/about">About</router-link>
<router-link to="/tab/contact">Contact</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
components: {
Home: () => import('./Home.vue'),
About: () => import('./About.vue'),
Contact: () => import('./Contact.vue')
},
created() {
// 当页面刷新时,检测当前路由地址并切换 Tab
this.switchTab()
},
methods: {
switchTab() {
const currentPath = this.$route.path
// 根据当前路由地址来判断应该选中哪个 Tab
// ...
}
}
}
</script>
2,在子组件中编写对应的内容
<template>
<div>Home Content</div>
</template>
3,在路由器中配置嵌套路由
const router = new VueRouter({
routes: [
{
path: '/tab',
component: Tab,
children: [
{
path: 'home',
component: Home
},
{
path: 'about',
component: About
},
{
path: 'contact',
component: Contact
}
]
}
]
})
4,定义一个监听路由变化的方法,当路由地址发生变化时调用该方法来切换 Tab
watch: {
$route() {
// 监听路由变化并切换 Tab
this.switchTab()
}
}
5,在 switchTab 方法中根据当前路由地址判断应该选中哪个 Tab
switchTab() {
const currentPath = this.$route.path
if (currentPath === '/tab/home') {
this.selectedTab = 'home'
} else if (currentPath === '/tab/about') {
this.selectedTab = 'about'
} else if (currentPath === '/tab/contact') {
this.selectedTab = 'contact'
}
}
$route 和 $router 的区别:
$router 指的是整个项目的路由配置,所以里面就包含了跳转路由的方法push、replace、go、back、forward
而 $route 指的是当前活跃的路由对象,所以能够获取当前页面的path、query、params
导航守卫
src/router/index.js
导航钩子的三个参数解析:
to: 即将要进入的目标路由对象
from: 当前导航即将要离开的路由对象
next: 调用该方法后,才能进入下一个钩子函数
例如实现一个用户详情的案例,必须要进行登录才能操作
// 定义导航守卫
router.beforeEach((to, from, next) => {
if (to.path == '/user' && from.path != '/detail') {
alert('请先登录');
next('/detail')
return;
}
next(); // 没有next()方法,导航不会跳转
})
实现KeepAlive缓存页面
修改App.vue
// 将原本的:
<router-view/>
// 修改为:
<keep-alive>
<router-view/>
</keep-alive>
如果只是针对某些页面缓存可以这样
<keep-alive>
<router-view v-if="$route.meta.keepAlive" />
</keep-alive>
<router-view v-if="!$route.meta.keepAlive" />
然后修改router/index.js 增加Router中的meta
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [
...,
{
path: '/',
name: 'index',
component: () => import('../views/index.vue'),
meta: {
keepAlive: true
}
},
{
path: '/home',
name: 'home',
component: () => import('../views/home.vue')
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router