文章目录
1、vue-router是什么
这里的路由不是平时说的硬件路由器,这里的路由就是SPA(单页应用)的路径管理器。vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适用于构建单页面应用。
vue的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来。
传统的页面应用,是用一些超链接来实现页面切换和跳转的。在vue-router单页面应用中,则是路径之间的切换,也就是组件的切换。路由模块的本质 就是建立起url和页面之间的映射关系。
至于我们为啥不能用a标签,这是因为用Vue做的都是单页应用(当你的项目准备打包时,运行npm run build时,就会生成dist文件夹,这里面只有静态资源和一个index.html页面),所以你写的标签是不起作用的,你必须使用vue-router来进行管理。
2、vue-router实现原理
SPA(single page application):单一页面应用程序,只有一个完整的页面;它在加载页面时,不会加载整个页面,而是只更新某个指定的容器中内容。单页面应用(SPA)的核心之一是: 更新视图而不重新请求页面;vue-router在实现单页面前端路由时,提供了两种方式:Hash模式和History模式;根据mode参数来决定采用哪一种方式。
2.1、Hash模式:
vue-router默认hash模式:使用URL的hash来模拟一个完整的URL,于是当URL改变时,页面不会重新加载。hash(#)是URL的锚点,代表的是网页中的一个位置,单单改变#后的部分,浏览器只会滚动到相应位置,不会重新加载页面。也就是说hash出现在URL中,但不会被包含在http请求中,对后端完全没有影响,因此改变hash不会重新加载页面。
同时每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用”后退”按钮,就可以回到上一个位置。所以说Hash模式通过锚点值的改变,根据不同的值,渲染指定DOM位置的不同数据。hash 模式的原理是 onhashchange 事件(监测hash值变化,在当前 URL 的锚部分发生修改时触发),可以在 window 对象上监听这个事件。
2.2、History模式:
由于hash模式会在url中自带#,如果不想要很丑的hash,我们可以用路由的history模式,只需要在配置路由规则时,加入mode: ‘history’,这种模式充分利用了html5 history interface 中新增的 pushState() 和 replaceState() 方法。这两个方法应用于浏览器记录栈,在当前已有的 back、forward、go 基础之上,它们提供了对历史记录修改的功能。只是当它们执行修改时,虽然改变了当前的 URL ,但浏览器不会立即向后端发送请求。
不过这种模式要玩好,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id
就会返回 404,这就不好看了。
所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html
页面,这个页面就是你 app 依赖的页面。
export const routes = [
{path: "/", name: "homeLink", component:Home}
{path: "/register", name: "registerLink", component: Register},
{path: "/login", name: "loginLink", component: Login},
{path: "*", redirect: "/"}]
此处就设置如果URL输入错误或者是URL 匹配不到任何静态资源,就自动跳到到Home页面。
3、使用路由模块来实现页面跳转的方法
- 方法1:直接修改地址栏
- 方法2:
this.$router.push('路由地址')
- 方法3:
<router-link to="路由地址"></router-link>
4、vue-router使用方法
- 1:下载
npm i vue-router -S
- 2:在main.js中引入
import VueRouter from 'vue-router'
; - 3:安装插件
Vue.use(VueRouter)
; - 4:创建路由对象并配置路由规则
let router = new VueRouter({routes:[{path:'/home',component:Home}]})
; - 5:将其路由对象传递给Vue的实例,options中加入
router:router
- 6:在app.vue中留坑
<router-view></router-view>
具体代码:
app.vue中“留坑“:
5、重定向和别名
5.1、重定向
“重定向”的意思是,当用户访问 /a
时,URL 将会被替换成 /b
,然后匹配路由为 /b
重定向也是通过 routes
配置来完成,从/a
重定向到/b
const router = new VueRouter({
routes: [
{ path: '/a', redirect: '/b' }
]
})
重定向的目标也可以是一个命名的路由:
const router = new VueRouter({
routes: [
{ path: '/a', redirect: { name: 'foo' }}
]
})
甚至是一个方法,动态返回重定向目标:
const router = new VueRouter({
routes: [
{ path: '/a', redirect: to => {
// 方法接收 目标路由 作为参数
// return 重定向的 字符串路径/路径对象
}}
]
})
注意导航守卫并没有应用在跳转路由上,而仅仅应用在其目标上。在上面这个例子中,为 /a
路由添加一个 beforeEnter
守卫并不会有任何效果。
5.2、别名
别名:/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a,就像用户访问 /a 一样。
const router = new VueRouter({
routes: [
{ path: '/a', component: A, alias: '/b' }
]
})
“别名”的功能让你可以自由地将 UI 结构映射到任意的 URL,而不是受限于配置的嵌套路由结构。
6、vue-router参数传递
声明式的导航<router-link :to="...">
和编程式的导航router.push(...)
都可以传参
6.1、用name传递参数
在路由文件router/index.js里面配置name属性
在模板里面用$router.name
来接收
6.2、通过<router-link>
标签中的to传参
基本语法:
<router-link :to="{name: 'aa', params: {key: value}}"></router-link>
router/index.js
{path: '/aa', name: 'aa', compoent: aa}
在模板里面用$router.params.key
来接收
6.3、利用url传递参数----在配置文件里以冒号的形式设置参数。
在router/index.js里面配置
{
path:'/params/:newsId/:newsTitle',
component:Params
}
7、命名视图
7.1、vue-router配置子路由(二级路由)
在原有的路由配置下加入children字段。
{
path: '/a',
name: 'pageA',
component: pageA,
children: [
{
path: '/c',
name: 'pageC',
component: pageB
},
{
path: '/d',
name: 'pageD',
component: pageUnit
}
]
}
7.2、单页面多路由区域操作
在一个页面里我们有两个以上<router-view>
区域,我们通过配置路由的js文件,来操作这些区域的内容
-
1、App.vue文件,在
<router-view>
下面新写了两行<router-view>
标签
-
2、需要在路由里配置components字段里进行
{
path: '/',
name: '/',
components: {
default: pageUnit,
pageA: pageA, // 显示A组件内容
pageB: pageB // 显示B组件内容
}
}
8、$route
和 $router
的区别
8.1、$route
$route是“路由信息对象”,包括path、params、hash、query、fullPath、matched、name等路由信息参数
-
$route.path
:字符串,对应当前路由的路径,总是解析为绝对路径。例如"/sy" -
$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
:当前路径名字
8.2、$router
$router 是“路由实例”对象,即使用 new VueRouter创建的实例,包括了路由的跳转方法,钩子函数等。
$router常见跳转方法:
this.$router.go(-1)//跳转到上一次浏览的页面
this.$router.replace('/menu')//指定跳转的地址
this.$router.replace({name:'menuLink'})//指定跳转路由的名字下
this.$router.push('/menu')//通过push进行跳转
this.$router.push({name:'menuLink'})//通过push进行跳转路由的名字下
$router.push
和$router.replace
的区别:
- 使用push方法的跳转会向history栈添加一个新的记录,当我们点击浏览器的返回按钮时可以看到之前的页面。
- 使用replace方法不会向history添加新纪录,而是替换掉当前的history记录,即当replace跳转到网页后,‘后退’按钮不能查看之前的页面。
9、404页面设置
用户会经常输错页面,当用户输错页面时,我们希望给他一个友好的提示页面,这个页面就是我们常说的404页面。vur-router也为我们提供了这样的机制。
-
1、设置我们的路由配置文件(router/index.js)
{ path:'*', component:Error }
这里的path:’*'就是输入地址不匹配时,自动显示出Error.vue的文件内容
-
2、在/src/components/文件夹下新建一个Error.vue的文件。简单输入一些有关错误页面的内容。
<template> <div> <h2>{{ msg }}</h2> </div> </template> <script> export default { data () { return { msg: 'Error:404' } } } </script>
此时我们随意输入一个错误的地址时,便会自动跳转到404页面。
进阶
1、导航守卫
每个守卫方法接收三个参数:
to:Route
:即将要进入的目标路由对象from:Route
:当前导航正要离开的路由next:function
:一定要调用这个方法来resolve这个钩子。执行效果依赖next
方法的调用参数。- next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
- next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到
from
路由对应的地址。 - next(’/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向
next
传递任意位置对象,且允许设置诸如replace: true
、name: 'home'
之类的选项以及任何用在router-link
的to
prop 或router.push
中的选项。
1.1、全局前置守卫
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中。
router.beforeEach((to, from, next) => {
console.log('这里打印的是即将要进入的页面信息');
console.log(to);
console.log('这里打印的是即将要离开的页面信息');
console.log(from);
next();
})
1.2、全局后置钩子
router.afterEach((to, from) => {
console.log('这里打印的是即将要进入的页面信息11 afterEach');
console.log(to);
console.log('这里打印的是即将要离开的页面信息11');
console.log(from);
});
1.3、路由独享的守卫
这些守卫与全局前置守卫的方法参数是一样的。
1.4、组件内的守卫
完整的导航接卸流程
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave
守卫。 - 调用全局的
beforeEach
守卫。 - 在重用的组件里调用
beforeRouteUpdate
守卫 (2.2+)。 - 在路由配置里调用
beforeEnter
。 - 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter
。 - 调用全局的
beforeResolve
守卫 (2.5+)。 - 导航被确认。
- 调用全局的
afterEach
钩子。 - 触发 DOM 更新。
- 调用
beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入。
2、路由元信息
-
1、路由定义
{ path: '/a', name: 'pageA', component: pageA, meta: {requiresAuth: true}, }
这里的
mate
字段就是路由元信息字段,requiresAuth
是自己起的字段名称,我们可以用这个字段来标记路由信息是否需要检测。(true表示需要检测、false表示不需要检测) -
2、js代码
router.beforeEach((to, from, next) => { //这里meta字段的名称要与上面route里面保持一致 if (to.matched.some(record => record.meta.requiresAuth)) { // this route requires requiresAuth, check if logged in // if not, redirect to login page. if (!this.loggedIn()) { // 自己的判断条件 next({ path: '/', // 重定向后的路由 query: {redirect: to.fullPath} // 登录成功之后可以根据query中的内容跳转回原来的路由(页面) }); } else { next(); } } else { next() // 确保一定要调用 next() } });
3、过渡效果
效果: