一.介绍
Vue Router 是 Vue.js 官方的路由管理器,或者说是SPA (单页面) 的路径管理器.通俗的说,vue-router 就是 WebApp的链接路径管理系统,在 vue-route 单页面应用中,是路径之间的切换和跳转的,也就是组件的切换,路由模块的本质就是建立起url和页面之间的映射关系
二.基本使用
1.开始
(1) 安装 vue-router 包
npm install --save vue-router
(2) 定义路由
创建route.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from './Home'
import Hello from './Hello'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/', // 访问的路径
name: 'Home',
component: Home // 视图对应的组件
}, {
path: 'hello',
name: 'Hello',
component: Hello
}
]
})
(3) 注册
在 main.js 中
import Vue from 'vue'
import App from './App.vue'
import router from './router'
new Vue({
router,
render: h => h(App)
}).$mount('#app')
此时,启动项目访问根路径
(4) hash路由和history区别
hash会在路径上添加#,类似锚点,不会跳转防止和后期的路由冲突推荐使用这个
如果要将#号去除那么就要使用history模式,可是使用history模式还有一个问题就是,在访问二级页面的时候,作刷新操做,会出现404错误,那么就须要和后端人配合让他配置一下apache或是nginx的url重定向,重定向到你的首页路由上就ok啦
const router = new VueRouter({
mode: "hash", //路径有#号,推荐这个
// mode: "history",
base: process.env.BASE_URL,
routes,
});
2.两种使用方式
(1) 声明式导航
<!-- 使用 router-link 组件来导航. -->
<!-- 通过传入 `to` 属性指定链接. -->
<router-link to="/hello">打开Hello</router-link>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
组件默认会在页面生成一个a标签,点击会跳转到to属性对应的地址。也可以写成如下形式:
<router-link :to="{path: '/hello'}">打开Hello</router-link>
<router-link :to="{name: 'Hello'}">打开Hello</router-link>
所有属性及说明
属性 说明:
to(必须) 目标路由地址
replace 替换当前路由,在历史记录栈中,用当前路由地址替换上一个路由地址。
append 目标路由地址为相对路径时有效,添加该属性,则在当前路径前添加基路径。
tag 默认值:“a”,router-link组件渲染在页面上的标签名称。
active-class 默认值:“router-link-activve”,链接激活时使用的css类名。
exact 精确匹配router-link是否为激活状态,不添加时,例如:访问’a/b/c’时,‘a’,'a/b’对应的router-link也为激活状态,添加exact属性后,‘a’,'a/b’则不会激活。
exact-active-class 默认值:‘router-link-exact-active’,router-link处于激活状态时的class类名。
(2) 编程式导航
路由跳转还可以通过router的实例方法实现,常用的方法有push(),replace(),go(),使用如下:
router.push('/hello')
router.push({name: 'Hello'})
router.push({path: '/hello'})
router.replace('/hello')
router.replace({name: 'Hello'})
router.replace({path: '/hello'})
router.go(1) // 前进一步
router.go(-1) // 后退一步
push() 和 replace() 使用方法基本一致,唯一区别在于push()往历史记录栈后插入一条新的记录,而replace()是替换当前记录,不会改变历史记录栈长度。使用go()方法时,如果传入的参数,超出当前历史记录栈范围,则不会发生跳转。
注意点: 在使用 router.push({path: ‘’, params: {}})形式时,参数将无法传递,params会被忽略
3.路由传参
(1) 布尔模式
如果 props 被设置为 true,route.params 将会被设置为组件属性。
// 路由中
{
path:"/about/:id",//动态路由
component:About,
props:true
}
// 组件中接收
props:['id']
(2) 对象模式
如果 props 是一个对象,它会被按原样设置为组件属性。当 props 是静态的时候有用。
// 路由中
{
path:"/about",//普通路由
component:About,
props:{
id:18
}
}
组件中
props:{
id:{
type:Number, //约束类型
default:12 //默认参数
}
}
(3) 函数模式
你可以创建一个函数返回 props。这样你便可以将参数转换成另一种类型,将静态值与基于路由的值结合等等
routes: [
{
path: '/search',
component: SearchUser,
props: route => ({ name: route.query.q }) //返回对象可以用()包住,
//或者
props:a=>{
return{
name:a.query.name
}
}
}
]
props:()=>({name:'张三'})
4.重定向和别名
(1) 重定向
router.js
routes: [
{
path: '/about',
name: 'About',
component: About,
}, {
path: '/other',
redirect: '/about'
}
]
说明:此时访问 localhost:8080/#/other 会被重定向到 localhost:8080/#/about路径。
redirect也可以是一个对象
{
path: '/other',
redirect: {name: 'About'}
}
(2) 别名
重定向是当 /a 被重定向到/b 时,主动访问/a 时,浏览器会自动跳转到 /b,而别名是当 /a 的别名为 /b 时,主动访问 /b 时,浏览器不会发生跳转,但是看到的内容时 /a 的内容,浏览器地址还是 /b。
routes: [
{ path: '/a', component: A, alias: '/b' }
]
5.配置404页面
当路由匹配不到的时候加载的组件
//定义到最后,因为路由的优先级是从上到下的
{
path:"*",
component:()=>import('a404.vue')
}
6.导航守卫
(1) 全局守卫
1.全局前置守卫
//to:route 即将要进入的目标路由对象
//from:route 当前导航正要离开的路由
//next:function 跳转到一个不同的地址
router.beforeEach((to , from ,next)=>{
if(to.name !=='Login' && !user){
next({name:"Login"}) //跳转到login命名路由
}else{
next() //允许跳转
}
})
2.全局解析守卫
router.beforeResolve()
3.全局后置钩子 (不接受next)
//你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:
router.afterEach((to, from) => {
// ...路由跳转之后做的操作
})
(2) 路由独享守卫
可以在路由配置上直接定义 beforeEnter 守卫
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
(3) 组件内守卫
1. beforeRouteEnter
注意: 不能访问this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。
beforeRouteEnter (to, from, next) {
next(vm => {
// 通过 `vm` 访问组件实例
})
}
2. beforeRouteUpdate
在当前路由改变,但是该组件被复用时调用
3. beforeRouteLeave
这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。
beforeRouteLeave (to, from, next) {
const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
if (answer) {
next()
} else {
next(false)
}
}
案例:
const Foo = {
template: `...`,
beforeRouteEnter(to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate() {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave(to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
7.路由元信息meta
定义路由的时候可以配置 meta 字段:
一个路由匹配到的所有路由记录会暴露为 $route 对象 (还有在导航守卫中的路由对象) 的 $route.matched 数组。因此,我们需要遍历 $route.matched 来检查路由记录中的 meta 字段。
{
path:"/",
meta:{title:"个人中心"}
}
// 在路由钩子中获取 meta 数据
//全局路由改变前钩子
router.beforeEach((to, from, next) => {
window.document.title = to.meta.title;
next();
})
// 在组件中读取 $route.meta.title
<template>
<div>
<h1>{{ $route.meta.title}}</h1>
</div>
</template>
// 动态改变 meta 数据
meta 数据并不是只读的,我们可以在代码中根据需求动态地改变它。
this.$route.meta.title = "还是首页";