Vue路由配置和使用
项目中引入路由模块
- yarn安装vue-router插件
yarn add vue-router
- 在项目目录中新建’route’文件夹,新建index.js和routes.js
- routes文件用于建立建立路由表,方便管理
//引入需要的路由文件,页面都存放在view文件夹中
import Father from '../../view/father.vue'
import Son from '../../view/son.vue'
//建立routes数组,数组内每一个对象就是一个路由配置
const routes = [
{
path : '/example', //设置路由路径,前面要加'/'
component : Father, //设置路由路径匹配的页面组件
name : 'father', //该选项可设置命名路由
children : [{ //可选配置项,用于设置子路由,子路由路径写法需要注意
path : 'son',
component : Son
}]
}
]
//导出路由表
export default routes
- index文件用于创建router实例,并导出实例对象
import Vue from 'vue' //引入vue
import VueRouter from 'vue-router' //引入vue-router
import routes from './routes' //引入路由表
Vue.use( VueRouter ) //在vue中使用路由插件
//创建路由实例对象
const router = new VueRouter({
routes,
mode : 'hash' //设置路由模式,共三种(hash、history、abstract)
})
//导出路由对象
export default router
- 项目入口文件main.js中引入路由
import router from './router' //引入路由模块
new Vue({
router, // 在根实例选项中注入路由
render: h => h(App),
}).$mount('#app')
至此,路由插件的引入完成
路由的基本使用
- 路由标签
vue中注册了’'标签作为路由标签(底层为a标签),通过设置 to 属性来控制路由跳转路径。
<template>
<router-link to = './xxx'></router-link> //跳转路径为to后面的地址
//命名路由还可以这样写
<router-link to = "{name :'father'}"></router-link>
</template>
- 路由展示区
除了设置router-link标签以外,模板中还必要一个路由展示区用于渲染路由页面
<template>
<router-link to = './xxx'></router-link> //跳转路径为to后面的地址
//命名路由还可以这样写
<router-link to = "{name :'father'}"></router-link>
<router-view></router-view> //跳转的页面内容将会在这里显示
</template>
- 给选中路由增加css样式
在路由切换时,被选中标签身上会增加’router-link-active’这一个类,代表该路由被选中了,所以我们可以为这个类添加样式,实现选中路由高亮的效果。
路由中数据请求和跨域的处理
- 在路由中数据请求是常见的,可以使用axios插件实现数据请求功能。
项目中加载axios插件
yarn add axios
main.js中引入axios插件
import axios from 'axios'
//我们可以讲axios方法绑定在vue实例的原型上,这样就可以直接调用他了
Vue.prototype.$ajax = axios //以后直接调用 this.$ajax 即可
- 为了解决前后端跨域问题,我们可以在配置文件中修改配置
在根目录下新建文件’vue.config.js’ (配置文件在vue官网)
module.exports = {
devServer: { //设置反向代理
proxy: {
'/ajax': { //'/ajax'是标识符,约定俗成选择目标源地址后第一个路径
target: 'http://m.maoyan.com', // 目标源
changeOrigin: true, // 是否修改源为本地地址
},
}
}
}
//【特别注意:修改配置文件后需要重启服务】
至此跨域问题解决,为了更好的管理和使用数据请求,建议单独在根目录下建立api文件夹,管理接口。
//创建接口模板
const BASE_URL = 'http://localhost:8080' //后期改为后端提供路径即可
//创建api接口对象
const api = {
//一个键值对即对应一个api接口
test : `${BASE_URL}/path路径/path路径` //使用模版字符串拼接请求地址
}
//导出api对象
export default api
这样在页面上只需要引入api对象即可使用接口
//axios的使用方法
this.$ajax ({
url : `${api.test}`,
params : { //数据请求参数
}
}).then ( res => { //返回值
console.log (res)
}).catch (err => { //错误信息
console.log (err)
})
路由的高级使用
- 路由传参和接参
通过路由标签router-link内的to属性绑定参数可以传递数据
两种方式 parmas / query
<template>
<router-link
:to = "{
name : 'test',
parmas : { //参数
id : '123'
},
}"
>
</router-link>
<router-link
:to = "{
name : 'test', //也可以使用 path :'/test'
query : { //参数
id : '123'
},
}"
>
</router-link>
</template>
//【特别注意:path和parmas不可同时使用,所以要避免混用】
可能会出现的问题 :
使用parmas传参会出现刷新页面丢参
解决方案:修改路由配置,在path后带上参数名
{
path : '/example',
component : Father,
name : 'father',
children : [{
path : 'son/:aaa/:bbb',
这样就绑定了aaa和bbb的数据
component : Son
}
路由接参 this.$route
表示当前激活的路由的状态信息,包含了当前 URL 解析得到的信息,还有 URL 匹 配到的 route records(路由记录)。
- 编程式导航
当不使用进行路由跳转时,vue还提供了另外的方法–编程式导航
实际上底层也是通过执行$router.push()进行跳转
关键词:$router
在$router对象下有push和replace两种方法可以用于跳转,这两种方法写法大体一致,唯一的不同就是replace方法不会向history中添加新的记录,而是替换掉当前的history记录,这就使历史记录后退功能失效。
写法:(以push方法为例)
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
另外在$router下还有一个go方法,它可以控制history记录中前进和回退。
router.go (1) //前进一步记录
router.go (-1) //后退一步记录
路由守卫
路由守卫适用于通过或者取消跳转来实现对路由的守卫,vue中共有三种路由守卫:
全局路由守卫,独享路由守卫和组件路由守卫。
1. 全局前置守卫
全局前置守卫可以通过使用router.beforeEach来注册
Q :什么是前置守卫?
A :导航一旦触发,所有的前置守卫就会依次调用,只有当所有前置守卫完成之后才会 根据前置守卫的状态来决定跳转还是取消跳转
const router = new VueRouter({option}); //创建的router实例对象
//全局下执行router.beforeEach方法注册全局守卫
router.beforeEach((to, from, next) => {})
//共有三个参数
// to :将要跳转的路由对象
// from :当前所在的路由 (或者说是即将离开的路由)
// next :用于结束这个注册,必要
// next中的参数
// next() /执行下一条语句,全部执行完成切换路由状态为confirmed,可以跳转
// next(false) /中断当前导航,重置url到from地址
// next('/') /跳转到一个地址
2. 全局后置钩子
不同于守卫,钩子在后方只是起到给用户提醒跳转确认的作用,因为后置钩子根本无法接收到next函数,所以也不能控制跳转。
router.afterEach((to, from) => {
})
3. 路由独享守卫
实际用法与全局前置守卫和后置钩子相同,只不过它是在路由表中就被定义了。所以他的作用域就只存在于该路由下。
routes: [
{
path: '/foo',
component: Foo,
//在该路由下注册了一个独享守卫(类似全局前置守卫)
beforeEnter: (to, from, next) => {
// ...
}
}
]
4. 组件内守卫
组件内守卫的作用范围进一步细化为单个组件,它可以直接在组件内定义,共有三种:
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
详细信息可访问Vue文档中关于导航部分的内容:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#组件内的守卫
5. 官方文档中关于完整导航解析的流程
- 导航被触发。
- 在失活的组件里调用离开守卫。
- 调用全局的
beforeEach
守卫。- 在重用的组件里调用
beforeRouteUpdate
守卫 (2.2+)。- 在路由配置里调用
beforeEnter
。- 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter
。- 调用全局的
beforeResolve
守卫 (2.5+)。- 导航被确认。
- 调用全局的
afterEach
钩子。- 触发 DOM 更新。
- 用创建好的实例调用
beforeRouteEnter
守卫中传给next
的回调函数。