vue-router是vue的核心插件,而当前vue项目一般都是单页面应用,也就是说vue-router是应用在单页面应用中的。
一、单页面应用与多页面应用
1、单页面(SPA)
单一页面应用程序,有且只有一个完整的页面;当它在加载页面的时候,不会加载整个页面的内容,而只更新某个指定的容器中内容。
在vue-router单页面应用中,则是路径之间的切换,也就是组件的切换。路由模块的本质 就是建立起url和页面之间的映射关系。
用js动态的将当前页面的内容清除掉,然后将下一个页面的内容挂载到当前页面上,这个时候的路由不是后端来做了,而是前端来做,判断页面到底是显示哪个组件,清除不需要的,显示需要的组件。这种过程就是单页应用,每次跳转的时候不需要再请求html文件了。
2、多页面
每一次页面跳转的时候,后台服务器都会给返回一个新的html文档,这种类型的网站也就是多页网站,也叫做多页应用。
原理是:传统的页面应用,是用一些超链接来实现页面切换和跳转的.
二、vue-router实现原理
单页面应用(SPA)的核心之一是:
1.更新视图而不重新请求页面;
2.vue-router在实现单页面前端路由时,提供了三种方式:Hash模式、History模式、abstract模式,根据mode参数来决定采用哪一种方式。
三、路由模式
vue-router 提供了三种运行模式:
● hash: 使用 URL hash 值来作路由。默认模式。
● history: 依赖 HTML5 History API 和服务器配置。查看 HTML5 History 模式。
● abstract: 支持所有 JavaScript 运行环境,如 Node.js 服务器端。
Hash模式
hash(#)是URL 的锚点,代表的是网页中的一个位置,单单改变#后的部分,浏览器只会滚动到相应位置,不会重新加载网页,也就是说 #是用来指导浏览器动作的,对服务器端完全无用,HTTP请求中也不会不包括#;同时每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用”后退”按钮,就可以回到上一个位置;
History模式
HTML5 History API提供了一种功能,能让开发人员在不刷新整个页面的情况下修改站点的URL,就是利用 history.pushState API 来完成 URL 跳转而无须重新加载页面;
通常情况下,我们会选择使用History模式,原因就是Hash模式下URL带着‘#’会显得不美观;我们可以用路由的 history 模式,只需要在配置路由规则时,加入"mode: 'history'",这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。但实际上,这样选择一不小心也会出问题;比如:
当用户直接在用户栏输入地址并带有参数时:
Hash模式:xxx.com/#/id=5 请求地址为 xxx.com,没有问题;
History模式: xxx.com/id=5 请求地址为 xxx.com/id=5,如果后端没有对应的路由处理,就会返回404错误;
为解决这一问题,vue-router提供的方法是:
在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。
此处就设置如果URL输入错误或者是URL 匹配不到任何静态资源,就自动跳到到Home页面
abstract模式
abstract模式是使用一个不依赖于浏览器的浏览历史虚拟管理后端。
根据平台差异可以看出,在 Weex 环境中只支持使用 abstract 模式。 不过,vue-router 自身会对环境做校验,如果发现没有浏览器的 API,vue-router 会自动强制进入 abstract 模式,所以 在使用 vue-router 时只要不写 mode 配置即可,默认会在浏览器环境中使用 hash 模式,在移动端原生环境中使用 abstract 模式。 (当然,你也可以明确指定在所有情况下都使用 abstract 模式)
四、vue-router的使用方式
- 下载 npm i vue-router -S
- 在main.js中引入 ** import VueRouter from 'vue-router';
- 安装插件 Vue.use(VueRouter);
- 创建路由对象并配置路由规则
- let router = new VueRouter({routes:[{path:'/home',component:Home}]});
- 将其路由对象传递给Vue的实例,options中加入 router:router
- 在app.vue中留坑 <router-view></router-view>
具体实现代码:
//main.js文件中引入
import Vue from 'vue';
import VueRouter from 'vue-router';
//主体
import App from './components/app.vue';
import index from './components/index.vue'
//安装插件
Vue.use(VueRouter); //挂载属性
//创建路由对象并配置路由规则
let router = new VueRouter({
routes: [
//一个个对象
{ path: '/index', component: index }
]
});
//new Vue 启动
new Vue({
el: '#app',
//让vue知道我们的路由规则
router: router, //可以简写router
render: c => c(App),
})
最后记得在在app.vue中“留坑”
//app.vue中
<template>
<div>
<!-- 留坑,非常重要 -->
<router-view></router-view>
</div>
</template>
<script>
export default {
data(){
return {}
}
}
</script>
五、导航
1、声明式导航&编程式导航
在浏览器中,点击链接实现导航的方式,叫做声明式导航。
例如:普通网页中点击 <a> 链接、vue 项目中点击 <router-link> 都属于声明式导航
在浏览器中,调用 API 方法实现导航的方式,叫做编程式导航。
例如:普通网页中调用 location.href 跳转到新页面的方式,属于编程式导航
2、vue-router中的编程式导航API
简化:在实际开发中,一般只会前进和后退一层页面。因此 vue-router 提供了如下两个便捷方法:
① $router.back()
- 在历史记录中,后退到上一个页面
② $router.forward()
- 在历史记录中,前进到下一个页面
六、路由守卫
路由守卫有三种:
1:全局钩子:全局前置守卫 beforeEach、 全局后置守卫afterEach
2:独享守卫(单个路由里面的钩子): beforeEnter、 beforeLeave
3:组件内守卫:beforeRouteEnter、 beforeRouteUpdate、 beforeRouteLeave
1、全局守卫 (beforeEach、afterEach)
1、全局前置守卫beforeEach
next 函数的 3 种调用方式最终导致的结果 :
当前用户拥有后台主页的访问权限,直接放行:next()
当前用户没有后台主页的访问权限,强制其跳转到登录页面:next(‘/login’)
当前用户没有后台主页的访问权限,不允许跳转到后台主页:next(false)
主要用于登录
2、 全局后置守卫afterEach(每次切换后被调用)
全局后置守卫是整个单页应用中每一次路由跳转后都会执行其中的回调。所以多用于路由跳转后的相应页面操作,并不像全局前置守卫那样会在回调中进行页面的重定向或跳转。
是路由跳转之后执行的事件,可以用作跳转路由后更改网页名
首先路由的meta需要配置title的名字
2、独享守卫(beforeEnter、beforeLeave)
beforeEnter:(to,from,next)=>{}
与全局路由守卫用法一致,但是只能针对一个页面使用
3、组件内守卫(beforeRouteEnter、 beforeRouteUpdate、 beforeRouteLeave)
1. beforeRouteEnter:(to,from,next)=>{}——到达
to,from参数与上面使用方法一致。next回调函数略有不同。
2. beforeRouteLeave:(to,from,next)=>{}——离开
点击其他组件时,判断是否确认离开。确认执行next();取消执行next(false),留在当前页面。
七、route和router的区别
route是一个跳转的路由对象,是当前路由信息,它是一个局部的对象,可以获取到当前路由地址参数等等,比如:name、path、params、query等
router是全局路由(VueRouter)实例对象,可以通过router进行路由的跳转、后退等,平常会用$router.push('')来进行路由的一个切换,它本质是向history栈中添加了一个路由,但在我们看就是路由的一个切换,也还会用$router.back()返回上一级的路由。