路由:分为前端路由和后端路由和route、router
-
后端路由表示地址栏发生变化,页面的内容也发生变化
-
前端路由(相当于一个对象):单页面应用,不同的用户事件显示不同的页面(地址与事件产生对应关系)
-
两种模式:
- a链接中#相当于描点(当前页面中跳转)
- hash:地址栏中有一个#号,#号后面发生变化就会触发hashchange事件
window.addEventListener('hashchange', ( )=> {
// 通过location.hash 获取到最新的hash值
console.log(location.hash);
})
- history:没有#号,h5新增的模式,需要后端服务器配置配合
history.pushState( { },title,url );// 向历史记录中追加一条记录
history.replaceState( { },title,url ); // 替换当前页在历史记录中的信息
window.addEventListenter( 'popstate', function(event) {
console.log(event)
} )
main.js
整个项目的入口文件
import { createApp } from 'vue' // 导入创建vue实例的方法
import App from './App.vue' // 导入根视图
import router from './router' // 导入路由的配置文件
//(导入的是router文件夹,默认会找index.js文件)
import store from './store' // 导入仓库的配置文件
// createApp(App).use(store).use(router).mount('#app')
// vue3:
// 创建vue实例
// 使用store插件
// 使用router插件
// 挂载实例 到 #app
const app = createApp(App);
app.use(store);
app.use(router);
app.mount('#app')
路由
路由的概念, vue-router的库已经给我们实现了前端路由,我们只要使用就可以了,
我们在创建时候已经选择vue-router这个库,所以我们直接使用就可以了
第一步
router/index.js 文件解析
// 导入创建路由的方法, 路由模式的方法
import { createRouter, createWebHashHistory , create } from 'vue-router'
// 导入了一个组件
import HomeView from '../views/HomeView.vue'
// 路由的配置文件
// 所有需要显示的页面,都需要在这个数组中配置
// 每一个元素都是一个对象
// 选项:
// path: 匹配的路径 /代表根目录
// component: 当前匹配到的路径要显示的视图
// path component 是一个路由配置必须要有的两个属性
// name是路由的别名(给这个路由取一个名字: 这名字不要和其他的路由名字重名了)
// 建议大家写上,通过name做路由跳转会比较方便
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
// 这个路由视图是使用了路由懒加载的方式加载的视图组件
// 这种加载方式是vue开发的优化项目的一种方式
// /* webpackChunkName: "about" */
// 这个注释最好不要删除,并不是一个简单的注释,最后打包项目
// 最后打包项目的时候,会给这个文件加这个chunkname, 为了方便的区分文件.
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
}
]
const router = createRouter({ // 创建路由实例
history: createWebHashHistory(), // 是使用哪种模式: hash history
routes // 路由的配置
})
export default router
第二步
有了路由的文件配置后,还需要有第二步: 就是要把视图加载出来
// 这个组件就是用来显示子路由的。 所有的路由视图都是通过这个组件显示出来的。
第三步
路由的跳转
声明式的导航
本质的就是a连接, 但是我们不要直接使用a连接,要使用它提供组件来去跳转
<!--
声明式的跳转
1.字符串, (需要跳转的路径)
2.对象 (里面是一个对象,可以通过path或者name去跳转)
// 对象的形式功能比较多,比如携带参数可以属性的方式
// 如果是字符串形式的话,就只能通过拼串的方式了
-->
<router-link to="/about">跳转转到about</router-link>
<br>
<router-link :to="{path:'/about'}">通过对象的形式跳转到about1</router-link>
<br>
<router-link :to="{name:'about'}">通过对象的形式跳转到about2</router-link>
<br>
<router-link :to="{name:'about',query: {name:'young',age:18}}">通过对象的形式跳转到about3</router-link>
编程式的导航
场景: 登录成功后要自动跳转到首页, 声明式的导航是否可以做到?
就需要用到编程式导航,或者其他的场景也是会用的到的
编程式导航是用的比较多的。一般项目中都是使用编程式导航来去做跳转的
因为 在mian.js中已经使用router插件,那么就会全局的对象中加一对象 ,$router
通过this.$router就可以完成编程式导航
<button @click="jump1">跳转到about-push</button>
<button @click="jump2">跳转到about-replace</button>
对应的操作的方式
对配置路由的跳转
methods: {
jump1(){
// console.log(this.$router)
/*
push() // 有记录的跳转
参数也有两种形式
1. 字符串 路由的path
2. 对象 可以通过name|path去跳转, 也可以属性来去携带参数
*/
// this.$router.push('/about')
// this.$router.push({name:'about'})
// this.$router.push({path:'about'})
// this.$router.push({
// name:'about',
// query:{name:'young',age:18}
// })
this.$router.push({
path: '/about',
query: {name:'young',age:18}
})
// 此时通过path和name没有什么区别, 都可以携带query参数
// 区别在于params的参数
},
jump2(){
// replace() 目标路由替换当前路径(没有记录的跳转)
// 参数的形式也和push一样
this.$router.replace('/about')
}
}
对浏览历史的的跳转
<button @click="jump3">返回</button>
<button @click="jump4">go方法</button>
<button @click="jump5">前进</button>
methods:{
jump3(){
this.$router.back(); // 返回
},
jump4(){
// this.$router.go(-2) // 负数表示返回多少页
this.$router.go(1) // 正数表示前进多少页
},
jump5(){
this.$router.forward() //前进
}
}
路由的配置
必要的属性就是两个path ,component
路由的参数
在path的值使用: 来配置参数
?代表这个参数可选
{
// 这个:id就要路由的参数 /info/后面的内容都会当做id参数
// 如果这个参数是可选的,就要用?来修饰一下
path: '/info/:id?',
name: 'info',
component: () => import('../views/Info.vue')
},
{
path: '/demo/:uid',
name: 'demo',
component: ()=>import('../views/Demo.vue')
},
获取参数: $route 获取路由对象信息 (接收参数:params,query)
this.$route.params.id
this. r o u t e . q u e r y 获取参数:要通过 t h i s . route.query 获取参数: 要通过this. route.query获取参数:要通过this.route
mounted(){
// 接受当前路由的参数
// 需要通过this.$route(不带r)来获取
// $router 路由对象-可以操作路由
// $route 路由信息对象(只是获取信息)
console.log(this.$route)
/*
params : 路由参数
query : 问号?后面的参数
path : 路径
href : 解析后的完整路径
name : 当前路由的name属性
*/
},
注意: parmas不能通过path来传,只能通过name跳
methods: {
jump(){
// 通过path方式跳转就不能带params
this.$router.push({
path: '/demo',
query : {name:'young', age: 18},
params: {uid: 'aaa123'} //路由参数
})
// 通过name跳 ,两种参数都可以带
// this.$router.push({
// name: 'demo',
// query : {name:'young', age: 18},
// params: {uid: 'aaa123'} //路由参数
// })
}
}
子路由
配置子路由需要2步
- 通过children子路由
- 需要在父路由视图中使用 来显示子路由的视图
{
path: '/parent',
name: 'parent',
component: ()=>import('../views/Parent.vue'),
// 子路由要通过children属性去配置
// 是一个数组, 里面的每一项也都是路由对象
children: [
{
path: '/son1', // 子路由的路径通常是不带 / 的, 因为/代表根路径
name: 'son1',
component: ()=>import('../views/Son1.vue')
// 子路由的视图要显示出来, 要通过父路由的视图的<router-view>
},
{
path: 'son2',
name: 'son2',
component: ()=>import('../views/Son2.vue')
}
]
},
Pararen.vue
<template>
<div>
<h2>这是parent视图</h2>
<router-view />
</div>
</template>
路由重定向
// 访问test的时候跳转到about
{
path:'test',
redirect: '/about'
}
router 操作路由的对象
导航守卫
监听路由的变化
某个守卫的钩子可以做路由的拦截
路由守卫执行规则:
先执行全局前置,再执行路由独享,最后执行组件内部的路由钩子,再执行生命周期的钩子
全局的前置守卫
路由的前置守卫,路由跳转前会执行,接收一个函数作为参数,这个函数就是跳转前要执行的函数
这个函数有三个参数(to, from, next)
to: 目标路由信息(要去哪里)
from:当前路由信息(来自哪里)
next:是一个方法,执行了才会跳转到目标路由(也可以跳转到指定路由)
router.beforEach( ( to, from, next ) => {
// 可以做个登录拦截:如果有登录才给访问后面的页面,如果没有就不给访问
// 拦截test页面的params就跳转到首页,否则就是调到目标路由
if ( to.params.id == 'aaa' ) {
next('/')
} else {
next( )
}
})
全局的后置守卫
跳转完了执行(不能再做拦截)
router.afterEach( ( to, from )=> {
} )
路由的独享守卫
在 router文件夹中index.js中的每个单独的路由信息中配置
const routes = [
{
path: '/about',
name:'about',
component: ( ) => import( '../views/Test.vue' ),
// 路由独享守卫
baforeEnter:(to,from)=> { // 只有访问到这个路由的时候才会执行
console.log('访问了about')
}
}
]
组件内部的守卫 接收两个参数 to,from
mounted(){
},
beforeRouteEnter(to,from) {
// 当进入了该路由时,就会执行这个路由函数
// 不可以获取组件实例‘this’
},
beforeRouteUpdate(to,from){
// 当前组件的路由发生变化,就会触发这个路由函数
},
beforeRouteLeave(to,from){
// 离开当前路由时调用
}
toC ( to client ) 面向客户
toB ( to business ) 给商家使用的(后台管理系统)