一、什么是vue-router
由于vue是单页面应用,当我们打包的时候,运行npm run build时,会生成dist文件夹,这里只有静态资源和一个index.html页面,所以当我们使用超链接进行页面跳转的时候是不起作用的,因为只有一个页面无法跳转,所以,在单页面应用中,我们必须通过路由来实现组件的切换,也就是页面的切换;路由模块的本质就是,建立起url和页面之间的映射关系。
二、vue- router实现的原理
SPA:单一页面应用,只有一个完整的页面;它在加载页面时候,不会加载整个页面,而是只更新某个指定的容器中的内容。单页面应用的核心是:更新视图而不重新请求页面;vue-router实现前端路由的时候,提供了两种模式:hash模式和history模式,可以指定mode参数设置不同的模式。
1、hash模式:
vue-router默认是hash模式,使用url的hash来模拟一个完整的url,于是当url改变时候,页面不会重新加载。hash(#)是URL锚点,代表网页中的一个位置,只改变#后面的部分时,浏览器只会滚动到相应位置,不会重新加载页面,也就是说hash出现在url中,但不会包含在http请求中,对完全没有影响,因此只改变hash不会重新加载页面。每次改变hash值都会在浏览器中添加一个历史记录,我们可以通过“后退”按钮就可以回到上一个位置。
所以说,hash模式是通过锚点值的改变,根据不同的值,渲染指定DOM位置的不同数据。hash模式的原理是window对象上监听onhashchange事件(检测hash值改变)。
2、history模式
html新增的pushState(), replaceState()方法,这两个方法应用于浏览器记录栈,在当前已已有的back、forward、go的基础上,他们提供了对历史记录修改的功能。只有当他们执行修改的时候,虽然改变了当前的UR L,但是浏览器不会立即向后端发送请求。
优点:history模式好看;
缺点:需要后端配合,当url匹配不到资源的时候,就应该返回同一个index.html页面
{path: "*", redirect:"/"}
3、使用路由模块进行页面跳转的方式
- 方式1: 直接修改地址栏,http://www.baidu.com/#/login
- 方式2: this.$router.push('路由') 编程式导航
- 方式3: <router-link to="路由地址"><router-link> 声明式导航
三、vue-router使用方式
- yarn add vue-router@3
- main.js中
- 引入 import VueRouter from 'vue-router'
- 全局安装插件 Vue.use(VueRouter)
- 引入路由对象 import router from './router/index'
- 配置
//mian.js import Vue from 'vue' import App from './App.vue' import VueRouter from 'vue-router' import router from './router' //全局挂在路由插件 Vue.use(VueRouter) new Vue({ router, render: h => h(App) }).$mount('#app')
- router/index.js中,创建路由对象并导出
//index.js
import VueRouter from 'vue-router'
import Login from './components/Login.vue'
//创建路由规则
const routes =[
{
path:'/login',
component: ()=>import{'./login.vue'}
}
]
//创建路由对象
const router = new VueRouter({
mode:hash,
routes
})
//导出路由对象
export default router
4.最后在app.vue中留坑
//app.vue中
<template>
<div>
//留坑非常重要
<router-view></router-view>
</div>
</template>
四、vue-router参数传递
声明式导航<router-link :to="...."></router-link> 和编程式导航 router.push(...)都可以传递参数
1、用name传递参数
- router/index.js文件中配置name属性
- 页面src/App.vue中用$route.name来接收 <p>{{$router.name}}</p>
const routes = [
{
path: './login',
name:'Hello',
component:Login
}
]
2、通过<router-link>标签中的to传递参数===params
基本语法
<router-link :to="{name:xxx, params:{key:value}}">链接显示文本<router-link>
-
//在src/App.vue中 <router-link :to="{name:'hi1', params:{username:'json', id:'555'}}">Hi页面</router-link> //在src/router/index.js中 { path:'/hi1', name:'hi1', component:Hi1 } //src/components/Hi1.vue中 $route.params.usernam接收 {{$route.params.username}} - {{$route.params.id}}
3、利用url传递参数 --- 在routes表中 以冒号的形式设置参数
当我们需要进行路由跳转的 时候,希望跳转时携带参数,则可以在path的url中定义参数,然后在app.vue中<router-link to=“/login/dingimiao/18”></router-link>,最后在页面中接受参数即可;
//在router/index.js中
{
path:'/login/:username/:age'
component:Login
}
//在App.vue中加入<router-link>标签
<router-link to="/params/dingmiao/18">跳转登录页面</router-link>
//在src/components/login.vue,可以使用url传递的数据
<template>
<div>
<p>名字: ${{$router.params.username}}</p>
<p>年龄: ${{$router.params.age}} </p>
</div>
</template>
4、使用path来匹配路由,然后通过to====query来传递参数
// 使用router-link
<router-link to="{name:'login', query:{username:'章三'}}"></router-link>
//src/router/index.js中
{
path:'/login',
name:'login',
component:Login
}
//在页面中获得参数
this.$route.query.username
五、嵌套路由
嵌套路由:在一个页面中可以展示不同的页面内容。
H1和H2页面嵌套在主页面《HelloWord》中,在该页面可以分别展示H1和H2 的页面。
1、首先用<router-link>标签增加两个新的导航链接;
<router-link :to="{name:'H1'}"></router-link>
<router-link :to="{name:"H2"}"></router-link>
2、在HelloWorld.vue文件中加入<router-view>标签,展示嵌套的页面
//HelloWord文件
<template>
<div>
<router-view></router-view>
</div>
</template>
3、创建H1 和 H2组件
4、修改router/index.js文件
子路由的<router-view>必须在HelloWord中出现
//router/index.js
routes:[
{
path:'/',
name:'HelloWord',
component:HelloWord,
children:[{path:'/h1', name:'H1',component:H1}, {path:'/h2',name:'H2', component:H2 }]
}
]
六、$route 和 $router的区别
$route是“路由信息对象”, 包括path, params, hash, query, fullPath, matched,name等信息参数。
- $route.path 字符串,对应当前路由的路径,总是解析为绝对路径,如“/order”
- $route.params 一个key/value对象,包含了动态片段和全匹配片段,如果没有路由参数就是一个空对象;
- $route.query 一个key/value 对象,表示URL查询参数;例如,对于路径/foo?user = 1,,则有$route.query.user 为1, 如果没有查询参数,则为各空对象;
- $route.hash 当前路由的hash值(不带#),如果没有hash值,则为空字符串
- $route.fullPath完成解析后的URL,包含查询参数和hash的完整路径;
- $route.matched 数组,包含当前路由匹配的路径中所包含的所有片段对应的配置参数对象。
- $route.name 当前路径的名字
$router是“路由实例”对象,即使用了new VueRouter创建实例,包含了路由的跳转方法,钩子函数等
$router常见的跳转方法
<button @click="goToMenue" ></button>
<script>
export default{
methods:{
goToMenue(){
this.$router.go(-1) //跳转到上一次浏览的页面
this.$router.replace('/menue') //指定跳转的地址
this.$router.replace({name:'menue'})//指定跳转路由的名字
this.$router.push('/menue') //通过push进行跳转
this.$router.push({name:'menuLink'}) //通过push进行跳转路由的名字下
}
}
}
</script>
$router.push 和 $router.replace的区别:
- 使用push方法的跳转会向history栈中添加一个新的记录,当我们点击浏览器的返回按钮时,可以看到之前的页面;
- 使用replace方法不会向history 添加新的记录,而是替换掉当前的history记录,即当replace跳转到的网页后,点击“后退”按钮时差看不到之前的页面。
七、设置404页面
1、在scr/index.js文件中,可以配置如下路由规则<含有通配符的路由应该放在最后>
这里*表示输入的路径不匹配时,自动显示Error.vue组件的的内容
2、新建Error.vue组件
{
path:'*',
component:Error
}
八、路由守卫
全局前置守卫、全局解析守卫、全局后置钩子、路由独享守卫、组件内的守卫
1、全局前置守卫
router.beforeEach((to, from , next) =>{
})
- to : Route : 即将要进入的目标 路由对象
- from:Route:当前导航正要离开的路由
- next: Function: 一定要调用这个方法来resolve这个钩子,执行效果以来next方法的调用参数。
next(): 进入管道中的下一个钩子,如果全部钩子执行完了,则导航的状态就是confied(确认的);
next('/') 或者next({path:'/'}):跳转到一个不同的地址;当前的导航被中断,然后进行一个新的导航,你可以向next传递任意位置对象
next(false): 中断当前的导航;
next(error):导航被终止,且该错误会被传递给router.ONError()注册过的回调
2、全局解析守卫
router.beforeResolve注册一个全局守卫,类似于全局路由守卫,但是是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用了。
3、全局后置钩子
afterEach区别于守卫,缺少了next函数为参数。
4、路由独享的守卫
可以在路由配置中直接定义beforeEnter守卫
const router = new VueRouter({
routes:[
{
path:'/foo',
component:Foo,
beforeEnter:(to, from, next)=>{
}
}]
})
5、组件内的守卫