vue Router的学习(一)
路由
route路由 就是一组key-value的对应关系
router路由器 多个路由需要经过路由器的管理
vue-router插件库 专门用来实现SPA (单页面程序)应用
对SPA 应用的理解
- 单页面web应用
- 整个应用只有一个完整的页面
- 点击页面中的导航链接不会刷新页面,只会做页面的局部更新
- 数据需要通过ajax请求获取
路由的理解
一个路由就是一组映射关系
key为路径,value为component用于展示页面内容
工作过程:当浏览器的路径改变时,对应的组件就会显示
基本使用
1.安装vue-router
$npm install vue-router
2.在main.js 引入vue-router 并且使用插件Vue.use(vueRouter)
// 引入vueRouter
import vueRouter from 'vue-router'
// 使用插件
Vue.use(vueRouter)
3.创建一个管理路由的文件 例如目前创建在router文件夹下的index.js文件
- 在文件中引入vue-router插件
- 并且引入components文件下的子组件
- 创建router实例对象,去管理我们的对应关系
- 最后默认导出router实例
// 引入vue-router
import vueRouter from 'vue-router'
import Home from '../components/Home'
import About from '../components/About'
// 创建router实例对象,让他去管理我们的对应关系
const router=new vueRouter({
routes:[
{
path:'/home',
component:Home
},
{
path:'/about',
component:About
},
]
});
export default router;
4.使用路由在我们的组件组长App.vue中进行组件间的切换
具体实现路由的切换是使用
<router-link to='/about'>About</router-link>
其中使用 一下标签可以指定显示位置
<router-view></router-view>
完整代码如下:
<template>
<div id="app">
<!-- <a href="#"> Home</a>
<a href="#">About</a> -->
<!-- 用于路径跳转 -->
<router-link to="/home" >Home</router-link>
<router-link to="/about"> About</router-link>
<!-- 容器 告诉vue通过路径拿到的组件放到哪里去 -->
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "App",
};
</script>
嵌套路由
多级路由
可在router index.js下的对应组件路由配置中添加children数组,里面可以添加子路由完成嵌套路由
实例中在Home.vue组件里嵌套详情details.vue:
routes: [
{
path: '/home',
component: Home,
// 嵌套路由
children: [
{
path: 'message',
component: Message,
children: [
{
path: 'details',
component: Details
}
]
},
{
path: 'news',
component: News
}
]
},
]
在home页面跳转时要写完整路径
<router-link to="/home/message">消息</router-link>
路由传参
跳转并携带query参数,to用拼接字符串形式传参
<router-link :to="'/home/message/details?id='+m.id">查看详情</router-link>
跳转并携带query参数,to用对象形式传参
<router-link :to="{
path: '/home/message/details', //完整路径
query: {
//携带的query参数,最终query中的东西,还是会以?id=+this.id拼接方式传递
id: m.id,
title: m.title,
},
}">
查看详情</router-link>
接收参数
$router.query.id
命名路由
给路由命名可以简化路由的跳转
使用:
1.给路由命名
{ name:'about', path:'/about', component:About}
2.简化跳转
<router-link :to="{
name:'about', //完整路径
query: {//携带的query参数,最终query中的东西,还是会以?id=+this.id拼接方式传递
id: 123
}, }">跳转到About组件</router-link>
路由的params参数
在配置路由的时候,使用占位符
{ name: 'details', //使用占位符
path: 'details/:id/:title',
component: Details
}
声明接受params参数
//字符串拼接的方式
<router-link to="/home/message/details/666/消息3">查看详情</router-link>//对象的形式接受参数
<router-link :to="{ //当使用params传递参数的时候,一定要使用name配置
name:'details',
params:{
id:m.id,
title:m.title
}}">查看详情</router-link>
编程式导航
除了使用 <router-link>
创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现
-
标签是声明式导航
-
router.push( …) 是编程式导航
router.push
方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL
<template> <div class="about">
<h2>我是About组件</h2> //声明式导航
<!-- <router-link :to="{name:'about'}"></router-link> -->
<!-- <p>{{ this.$route.params }}</p> -->
//编程式导航
<span @click="toHome">跳转Home</span>|
<span @click="messageHandler">跳转message</span>
<span @click="forwardHandler">前进一步</span>|
<span @click="backHandler">后退一步</span>|
<span @click="goHandler">去</span>
</div>
</template>
<script>
export default {
name: "About",
methods: { //跳转并且传递参数
toAbout() { // 进行路由跳转
console.log(this.$router.push);
this.$router.push({
//1.使用query进行传参,会将参数暴露拼接在url上
// path:'/about',
// query:{
// id:123
// }
// 2.params形式不暴露参数在url上
name: "home",
params: {
id: 666, }, }); },
//无参形式的跳转
//使用完整路径进行跳转
messageHandler(){
this.$router.push('/home/message') }, forwardHandler() { //使用原型里的forward方法前进一步
this.$router.forward(); },
backHandler() {
//使用原型里的back方法后退一步
this.$router.back();
// window.history.back() },
goHandler() {
//使用原型里的go方法设置进退步数,负数为后退
this.$router.go(2);
}, },};
</script>
<style scoped>
</style>
注意:如果提供了 path
,params
会被忽略,上述例子中的 query
并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name
或手写完整的带有参数的 path
:
const userId = '123'router.push({
name: 'user', params: { userId }})// -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user
重定向和别名
通过redirect属性将组件跳转路径进行重新定位
const router = new VueRouter({
routes: [ { path: '/a', redirect: '/b' } ]
})
路由的模式 hash history
vue-router 默认 hash 模式 —— 使⽤ URL 的 hash 来模拟⼀个完整的 URL,于是当 URL 改变时,⻚⾯不会重新加载。如果不想要很丑的 hash,可以⽤路由的 history 模式。
可以通过mode属性进行模式的设置
const router = new VueRouter({ mode:history})
两种模式的区别:
hash模式的url显示链接会默认添加#在根目录后
history模式是以正常的url进行显示
路由守卫
作用:对路由进行权限控制 鉴定权限
全局守卫
分成两个阶段
1.全局前置守卫,初始化时执行、每次切换路径时执行
2.全局后置守卫,初始化执行、每次路经切换后执行
// 全局前置守卫 1.在初始化的时候调用 2.当路由发生切换的时候调用
router.beforeEach((to, from, next) => {
// console.log('beforeEach');
console.log(to);
console.log(from);
console.log(next);
// console.log(localStorage.getItem('school'));
if (to.path === '/home/message') {
if (localStorage.getItem('school') === 'briup') {
// 判断存储中school的值是否为briup 如果是,放行
next() }
} else {
// alert('你不是briup的学生')
next()
}})//全局后置守卫,初始化执⾏、每次路由切换后执⾏
router.afterEach(() => {
console.log('****');
})
独享守卫
{
// 给路由命名
name: 'message',
path: 'message',
component: Message,
// 独享守卫
beforeEnter:(to,from,next)=>{
console.log('我是message的独享守卫');
if (to.path === '/home/message') {
if (localStorage.getItem('school') === 'briup') {
// 判断存储中school的值是否为briup 如果是,放行
next()
}else{
alert('你不是briup的学生')
}
} else {
next()
}
},
组件内守卫
一般有三个阶段
最后,你可以在路由组件内直接定义以下路由导航守卫:
beforeRouteEnter(to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
next(vm => {
// 通过 `vm` 访问组件实例
})
},
//2.2新增方法
beforeRouteUpdate(to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
this.name = to.params.name
next()
},
beforeRouteLeave(to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
//用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消
const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
if (answer) {
next()
} else {
next(false)
}
}
记住参数或查询的改变并不会触发进入/离开的导航守卫
完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave
守卫。 - 调用全局的
beforeEach
守卫。 - 在重用的组件里调用
beforeRouteUpdate
守卫 (2.2+)。 - 在路由配置里调用
beforeEnter
。 - 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter
。 - 调用全局的
beforeResolve
守卫 (2.5+)。 - 导航被确认。
- 调用全局的
afterEach
钩子。 - 触发 DOM 更新。
- 调用
beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入。