路由文档:
使用vue做spa应用的话,一定会涉及到路由。
安装
安装router插件
npm install vue-router
router的基本使用步骤
引入router插件——>配置路由——>实例化路由——>根实例注册路由——>页面挂载路由节点
router.js编写
在src下新建一个router.js, 接下来编写这个router.js
引入router插件
实例化VueRouter
mode:
默认为hash
,但是用hash
模式的话,页面地址会变成被加个#
号比较难看了, http://localhost:8080/#/linkParams/xuxiao
history
模式,它会使得我们的地址像平常一样。http://localhost:8080/linkParams/xuxiao
base应用的基路径。例如,如果整个单页应用服务在 /app/ 下,然后 base 就应该设为 "/app/"。
一般写成__dirname
,在webpack中有配置。 routesroutes
就是我们的大核心了,里面包含我们所有的页面配置。
routes配置介绍
path
就是我们的访问这个页面的路径
name
给这个页面路径定义一个名字,当在页面进行跳转的时候也可以用名字跳转,要唯一哟component
组件,就是咱们在最上面引入的 import ...
了,当然这个组件的写法还有一种懒加载
懒加载的方式,我们就不需要再用import
去引入组件了,直接如下即可。懒加载的好处是当你访问到这个页面的时候才会去加载相关资源,这样的话能提高页面的访问速度。
component: resolve => require(['./page/linkParamsQuestion.vue'], resolve)
在router.js文件末尾导出路由配置
紧接着在根实例注册router
在app中挂载路由页面
Hello App!
页面访问
比如routes配置如下:
页面访问地址:
页面跳转
1、使用router-link,注意to的值要和router.js文件中配置的path一致。
2、还可以在方法里利用 this.$router.push('xxx')
来进行跳转。
// 字符串,这里的字符串是路径path匹配噢,不是router配置里的namethis.$router.push('home')// 对象this.$router.push({ path: 'home' })// 命名的路由 这里会变成 /user/123this.$router.push({ name: 'user', params: { userId: 123 }})// 带查询参数,变成 /register?plan=privatethis.$router.push({ path: 'register', query: { plan: 'private' }})
动态路由
静态路由:path中的路径是写死的
动态路由:能传递参数的路由模式,由于可以传递参数,所以其对应的路由数量是不确定的,故称之为 动态路由
那么如何将参数作为路由呢?
在参数名前面加上 :
,然后将参数写在路由的 path
内
routes: [ //将页面组件与path指令的路由关联 { name: 'BookInfo', path: '/books/:id', component: BookInfo } ]
这样定义之后,vue-router
就会匹配所有的:/books/1,/books/2,/books/3 ……
,所以说这样定义的路由的数量是不确定的。
如何给路由传参呢?
1、在<router-link>
我们加入一个 params
属性来指定具体的参数值
上面的链接对应就为:
如果需要传入多个参数值,只要按照上面的命名方法来加入参数,传递在params中对应的声明参数值即可,vue-router只要匹配到路由模式的定义就会自动对参数进行分解取值
如 path: '/books/:version/:id',则对应params为:params :{id:1,version:1}
如何将这些参数读取出来呢?
通过 $route.params
这个属性获取指定的参数值
在相应的组件页面内输出参数值,对应代码如下:
当前图书编号是:{
{$route.params.id}}
如果想在js
代码中根据参数值做相应的处理,则在默认路由中加入如下代码:
export default { name: "app", created() { alert(this.$route.params.id); }};
2、使用 "/path?param = value"
的方式传递参数
{ name: 'BookInfo', path: '/books/:id/?bookName=Lost', component: BookInfo }
使用 "/path?param = value"
的方式传递参数,可以使用$route.query.参数名
获取参数值
获取其中 bookName
的值的代码为 this.$route.query.bookName
3、vue-router 还提供一种常量参数定义 meta
(),可以放一些key-value进去,方便在钩子函数执行的时候用。我们可以在路由定义中先定义 meta
的值,然后在路由实例中通过$route.meta
参数获取具体常量值。
{ name: 'BookInfo', path: '/books/:id', component: BookInfo ,meta: { bookName : 'Lost In River' }}
获取其中 bookName
的值的代码为 this.$route.meta.bookName
动态路由组件复用造成的问题
当使用路由参数的时候,如 从/books/1 到 /books/2 ,原来的组件实例会被复用,因为两个路由都渲染同一个组件,比起销毁后再创建,复用的销率会更高。
这也就是说 组件的生命周期钩子不会再被调用(组件没有被销毁后再创建) ,即 created mounted 等钩子函数在页面第二次加载的时候回失效。那么,当复用组件时候,想对路由参数的变化做出响应的话,就需要在 $watch
对象内添加对 $route
对象变化的跟踪函数
路由钩子
路由钩子主要是给使用者在路由发生变化时进行一些特殊的处理而定义的,比如当路由跳转前或跳转后,进入、离开某一个路由前、后,就可以使用路由钩子来监听路由的变化。
钩子函数根据其生效的范围可以分为 全局钩子函数
、路由独享钩子函数
和组件内钩子函数
。
全局钩子
直接在路由配置文件中写的钩子函数,在进入此路由配置时,可以做一些全局性的路由拦截。
router.beforeEach((to, from, next) => { //会在任意路由跳转前执行,next一定要记着执行,不然路由不能跳转了 console.log('beforeEach') console.log(to,from) // next() }) // router.afterEach((to, from) => { //会在任意路由跳转后执行 console.log('afterEach') })
我们在params路由里配置了beforeEnter得钩子函数,函数我们采用了ES6的箭头函数,需要传递三个参数。我们并在箭头函数中打印了to和from函数。具体打印内容可以在控制台查看object。
三个参数:
- to:路由将要跳转的路径信息,信息是包含在对像里边的。
- from:路径跳转前的路径信息,也是一个对象的形式。
- next:路由的控制参数,常用的有next(true)和next(false)。
-
next(false): 中断当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
-
next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。
某个路由独享钩子
就像说的一样,给某个路由单独使用的,本质上和后面的组件内钩子是一样的。都是特指的某个路由。不同的是,这里的一般定义在router当中,而不是在组件内。如下
const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { // ... }, beforeLeave: (to, from, next) => { // ... } } ]})
组件内钩子
更细粒度的路由拦截,只针对一个进入某一个组件的拦截。
首先看一下官方定义:
你可以在路由组件内直接定义以下路由导航钩子beforeRouteEnterbeforeRouteUpdate (2.2 新增)beforeRouteLeave
路由组件!路由组件!路由组件!重要的事情说三遍,大家一定要注意这里说的是“路由组件”,而路由组件!== 组件,路由组件!== 组件,路由组件!== 组件!之前一直没注意这点,然后在子组件里面傻乎乎的调钩子函数发现一直没用。
我们先来看一下什么是路由组件?
路由组件:直接定义在router中component处的组件
也就是说router中定义的入口vue文件之外的组件,是没有钩子函数的,也就不用说使用了。但是如果你使用了并不会报错,只是没反应。
const Foo = { template: `...`, beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 `this` // 因为当钩子执行前,组件实例还没被创建 ... next() }, beforeRouteUpdate (to, from, next) { // 在当前路由改变,但是该组件被复用时调用 // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候, // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。 // 可以访问组件实例 `this` ... next() }, beforeRouteLeave (to, from, next) { // 导航离开该组件的对应路由时调用 // 可以访问组件实例 `this` ... next() }}
钩子函数使用场景
其实路由钩子函数在项目开发中用的并不是非常多,一般用于登录态的校验,没有登录跳转到登录页;权限的校验等等。当然随着项目的开发进展,也会有更多的功能可能用钩子函数实现会更好,我们知道有钩子函数这个好东西就行了,下次遇到问题脑海就能浮现,噢,这个功能用钩子实现会比较棒。我们的目的就达到了。当然,有兴趣的可以再去研究下源码的实现。开启下脑洞。
其他知识点
在利用vue-router
去做跳转的时候,到了新页面如果对页面的滚动条位置有要求的话,可以利用。
参考文章: