目录
编程式导航,可以使用path-query传参、name-params传参和name-query传参
vue-router是vue的一个插件,用来提供路由功能。通过路由的改变可以动态加载组件,达到开发单页面程序的目的。
安装
方式一 :CDN引入
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.0-beta.7/vue.cjs.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/vue-router/4.0.10/vue-router.cjs.js"></script>
方式二:本地引入(js包)
<!-- 使用路由,先引入vue,再引入vueRouter -->
<script src="./js/vue-2.6.12.js"></script>
<script src="./js/vue-router-3.4.3.js"></script>
方式三:cnpm下载
cnpm install vue-router
使用
1、先引入vue,再引入vueRouter---<script src=''>
2、定义一个路由对象数组,由route路由对象组成---[{},{},{}]
3、创建路由器对象router(声明路由器对象实例)---new VueRouter
4、注册路由器对象(将路由实例对象导入vue实例对象)---router
5、使用路由(实现路由切换)---<router-link to=''>
6、路由组件显示的位置(路由出口,匹配路由组件,渲染到这个区域)---<router-view>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 1、使用路由,先引入vue,再引入vueRouter -->
<script src="./js/vue-2.6.12.js"></script>
<script src="./js/vue-router-3.4.3.js"></script>
</head>
<body>
<div id="app">
<!-- 5、使用路由(实现路由切换) -->
<div>
<router-link to="/a">去A路由</router-link>
<router-link to="/b">去B路由</router-link>
</div>
<div>
<!-- 6、路由组件显示的位置(路由出口,匹配路由组件,渲染到这个区域) -->
<router-view></router-view>
</div>
</div>
<script>
// 声明组件
let myA={
template:`
<div>A组件</div>
`
};
let myB={
template:`
<div>B组件</div>
`
};
// 2、定义一个路由对象数组,由route路由对象组成
let routes=[
{
path:'/',
},
{
path:'/a',
component:myA
},{
path:'/b',
component:myB
}
];
// 3、创建路由器对象router(声明路由器对象实例)
let router=new VueRouter({
// 声明配置路由对象
routes:routes
});
new Vue({
el:'#app',
// 4、注册路由对象(将路由实例对象导入vue实例对象)
// router:router,
router,
// 局部注册组件
components:{
'my-a':myA,
'my-b':myB
},
data:{
},
methods: {
},
})
</script>
</body>
</html>
router-link的本质是a标签
重定向
path和redirect实现重定向
name(大名)和redirect实现重定向
alias重命名(小名)
let routes=[
{
// path和redirect实现重定向
path:'/',
redirect:'/a'
},
{
path:'/a',
// 重命名(小名)
alias:'/aa',
component:myA
}
];
let routes=[
{
path:'/',
// name(大名)和redirect实现重定向
redirect:{name:'aRoute'}
},
{
path:'/a',
name:'aRoute',
// 重命名(小名)
alias:'/aa',
component:myA
}
];
动态路由匹配
需要把某种模式匹配到的所有路由,全部映射到同一个组件。
例如 : 有一个user组件,对于所有id不同的用户,都要使用这个组件来渲染,那么可以在vue-router的路由路径中使用动态路径参数来达到这个效果。
1、路由器对象中path可以携带参数---path:'/user/id/:id/username/:username'
2、组件中created()接收路由器对象传递的参数---this.id=this.$route.params.id;
// 声明组件
let myA={
data(){
return{
id:null,
username:'',
}
},
// 接收路由器对象传递的参数
created() {
// console.log(this.$route,'路由对象');
this.id=this.$route.params.id;
this.username=this.$route.params.username;
},
template:`
<div>A组件--{{id}}--{{username}}</div>
`
};
// 定义一个路由对象数组,由route路由对象组成
let routes=[
{
path:'/user/id/:id/username/:username',
component:myA
}
];
想对路由参数的变化作出响应的话,可以使用监听器或路由守卫
监听器---$route(to,from){ }---$route.params.xx
路由守卫---beforeRouteUpdate(to,from,next){ }---to.params.xx
// 声明组件
let myA={
data(){
return{
id:null,
username:'',
}
},
// 监听路由的变化并渲染到页面
// 法一:监听器
watch:{
$route(to,from){
// to是新路由,from是旧路由
console.log(to,from,'监听路由参数变化');
this.id=this.$route.params.id;
this.username=this.$route.params.username;
}
},
// 法二:路由守卫
beforeRouteUpdate(to,from,next){
// console.log(to.params,'路由参数');
this.id=to.params.id;
this.username=to.params.username;
// 继续向下执行
next();
// 阻断继续向下执行
next(false);
},
template:`
<div>A组件--{{id}}--{{username}}</div>
`
};
// 1、定义一个路由对象数组,由route路由对象组成
let routes=[
{
path:'/user/id/:id/username/:username',
component:myA
}
];
嵌套路由
1、在父亲路由对象中设置二级路由
2、在父组件中使用子路由
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 使用路由,先引入vue,再引入vueRouter -->
<script src="./js/vue-2.6.12.js"></script>
<script src="./js/vue-router-3.4.3.js"></script>
</head>
<body>
<div id="app">
<!-- 使用路由(实现路由切换) -->
<div>
<router-link to="/user">用户界面</router-link>
<router-link to="/manager">管理员界面</router-link>
</div>
<div>
<!-- 路由组件显示的位置(路由出口,匹配路由组件,渲染到这个区域) -->
<router-view></router-view>
</div>
</div>
<script>
// 声明组件
let myA = {
template: `
<div>用户</div>
`
};
let myB = {
template: `
// 在父组件中使用子路由
<div>
<div>
<router-link to="/managerChild1">子组件1</router-link>
<router-link to="/managerChild2">子组件2</router-link>
</div>
<div>
<!-- 路由组件显示的位置(路由出口,匹配路由组件,渲染到这个区域) -->
<router-view></router-view>
</div>
</div>
`
};
let child1 = {
template: `
<div>子组件1</div>
`
};
let child2 = {
template: `
<div>子组件2</div>
`
};
// 定义一个路由对象数组,由route路由对象组成
let routes = [
{
path: '/user',
component: myA
},
{
path: '/manager',
component: myB,
// 重定向
redirect:'/managerChild1',
// 在父亲路由对象中设置二级路由
children: [
{
path: '/managerChild1',
component: child1
}, {
path: '/managerChild2',
component: child2
}
]
}
];
// 创建路由器对象router(声明路由器对象实例)
let router = new VueRouter({
// 声明配置路由对象
routes: routes
});
new Vue({
el: '#app',
// 注册路由对象(将路由实例对象导入vue实例对象)
// router:router,
router,
// 局部注册组件
components: {
'my-a': myA,
'my-b': myB
},
data: {
},
methods: {
},
})
</script>
</body>
</html>
编程式导航
除了使用 <router-link>创建 a 标签来定义导航链接,还可以借助 router 的实例方法,通过编写代码来实现。this.$router.push()跳转到指定路由,会向history栈添加一个新的记录,当用户点击浏览器回退按钮的时候,可以回到跳转前的url。
1、点击按钮跳转到指令路由---<button @click="$router.push('/a')">
2、组件中created()接收路由器对象传递的参数---console.log(this.$route);
编程式导航,可以使用path-query传参、name-params传参和name-query传参
path-query传参 ---参数会被拼接在浏览器地址栏中,并且刷新页面后数据也不会丢失
name-params传参 ---一次性携带参数,页面刷新参数失效
name-query传参
1、点击按钮触发事件
2、书写事件方法传递参数(编程式导航)---this.$router.push({ })
3、组件中created()接收参数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 使用路由,先引入vue,再引入vueRouter -->
<script src="./js/vue-2.6.12.js"></script>
<script src="./js/vue-router-3.4.3.js"></script>
</head>
<body>
<div id="app">
<!-- 使用路由(实现路由切换) -->
<div>
<router-link to="/a">去A路由</router-link>
<router-link to="/b">去B路由</router-link>
</div>
<div>
<!-- 路由组件显示的位置(路由出口,匹配路由组件,渲染到这个区域) -->
<router-view></router-view>
</div>
<!-- 编程式导航跳转 -->
<button @click="$router.push('/a')">跳转去A路由</button>
<button @click="$router.push('b')">跳转去B路由</button>
<!-- 编程式导航跳转并传递参数 -->
<button @click="toPathA">跳转去A路由并传递参数</button>
<button @click="toPathB">跳转去B路由并传递参数</button>
</div>
<script>
// 声明组件
let myA={
data(){
return{
id:null,
username:''
}
},
template:`
<div>A组件--{{id}}--{{username}}</div>
`,
// 接收参数
created() {
console.log(this.$route);
// path直接传参或query传参
this.id=this.$route.query.id;
this.username=this.$route.query.username;
},
};
let myB={
template:`
<div>B组件</div>
`,
// 接收参数
created(){
console.log(this.$route,'打印路由器对象');
}
};
// 定义一个路由对象数组,由route路由对象组成
let routes=[
{
path:'/a',
component:myA
},{
path:'/b',
component:myB,
// name配合query进行参数传递
name:'bRoute'
}
];
// 创建路由器对象router(声明路由器对象实例)
let router=new VueRouter({
// 声明配置路由对象
routes:routes,
});
new Vue({
el:'#app',
// 注册路由对象(将路由实例对象导入vue实例对象)
// router:router,
router,
// 局部注册组件
components:{
'my-a':myA,
'my-b':myB
},
data:{
},
methods: {
// 跳转到A页面
toPathA(){
// 编程式导航
this.$router.push({
// 传递参数
// 法一:直接拼接在地址栏上
// path:'/a?id=1&username="张三"',
// 法二:path-query
path:'/a',
query:{id:1,username:"李四"}
// path-params无效!
// params:{
// id:1,
// username:'王五'
// }
})
},
// 跳转到B页面
toPathB(){
this.$router.push({
name:'bRoute',
// 法三:name-query进行参数传递
query:{id:1,username:'赵六'},
// 法四:name-params进行参数传递(一次性参数)
params:{gender:'男'}
})
}
},
})
</script>
</body>
</html>
路由模式
vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。如果不想要很丑的 hash,可以用路由的history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。不过这种模式要玩好,还需要后台配置支持。
hash模式
hash模式的工作原理是hashchange事件,可以在window监听hash的变化。我们在url后面随便添加一个#xx触发这个事件。
window.onhashchange = function(event){
console.log(event);
// 打印出一个HashChangeEvent事件对象,在该对象内有newURL和oldURL
// location.hash中也有相关的信息
// 假设hash值是个颜色值,通过location.hash来获取到对应的hash值,然后设置页面中的某个元素的背景颜色来改变页面
}
history模式
把window.history对象打印出来可以看到里边提供的方法和记录长度
history对象内有back(),forword(),go()等方法(前进,后退,跳转操作)
history.go(-3);//后退3次
history.go(2);//前进2次
history.go(0);//刷新当前页面
history.back(); //后退
history.forward(); //前进
hash路由和history路由的区别:
1、hash路由在地址栏URL上有#,而history路由没有会好看一点
2、进行回车刷新操作,hash路由会加载到地址栏对应的页面,而history路由一般就404报错了(刷新是网络请求,没有后端准备时会报错)。
3、hash路由支持低版本的浏览器,而history路由是HTML5新增的API。
4、hash的特点在于它虽然出现在了URL中,但是不包括在http请求中,所以对于后端是没有一点影响的,所以改变hash不会重新加载页面,所以这也是单页面应用的必备。
5、history运用了浏览器的历史记录栈,之前有back,forward,go方法,之后在HTML5中新增了pushState()和replaceState()方法(需要特定浏览器的支持),它们提供了对历史记录进行修改的功能,不过在进行修改时,虽然改变了当前的URL,但是浏览器不会马上向后端发送请求。
// 创建路由器对象router(声明路由器对象实例)
let router=new VueRouter({
// 声明配置路由对象
routes:routes,
// 切换路由模式
mode:'hash'
// mode:'history'
});
导航守卫
路由的改变会触发导航守卫
全局守卫(全局前置守卫、全局后置守卫)
全局前置守卫---router.beforeEach((to, from, next) => { })
全局后置钩子---router.afterEach((to, from) => { })
to: 即将要进入的目标路有对象
from: 当前导航正要离开的路由
next: Function : 一定要调用该方法来resolve这个钩子。执行效果依赖 next 方法的调用参数
路由独享守卫
该守卫与全局前置守卫的方法参数是一样的,且一定要调用该方法来resolve这个钩子
beforeEnter(to, from, next) => { }
组件内的守卫
beforeRouteEnter(to,from,next){ }---// this--window
beforeRouteUpdate(to,from,next){ }---//this--组件实例
beforeRouteLeave(to,from,next){ }---//this--组件实例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 使用路由,先引入vue,再引入vueRouter -->
<script src="./js/vue-2.6.12.js"></script>
<script src="./js/vue-router-3.4.3.js"></script>
</head>
<body>
<div id="app">
<!-- 使用路由(实现路由切换) -->
<div>
<router-link to="/a">去A路由</router-link>
<router-link to="/b">去B路由</router-link>
</div>
<div>
<!-- 路由组件显示的位置(路由出口,匹配路由组件,渲染到这个区域) -->
<router-view></router-view>
</div>
</div>
<script>
// 声明组件
let myA={
data(){
return{
id:null,
username:''
}
},
template:`
<div>A组件--{{id}}--{{username}}</div>
`,
// 组件内的守卫
beforeRouteEnter (to, from, next) {
console.log(this,'beforeRouteEnter');
// this指向全局对象window
next();
},
beforeRouteLeave (to, from, next) {
console.log(this,'beforeRouteLeave');
// this指向组件实例
},
beforeRouteUpdate(to, from, next) {
console.log(this,'beforeRouteUpdate');
// this指向组件实例
}
};
let myB={
template:`
<div>B组件</div>
`,
};
// 定义一个路由对象数组,由route路由对象组成
let routes=[
{
path:'/a',
component:myA,
// 路由独享守卫
// beforeEnter(to,from,next){
// console.log(to,from,'路由独享守卫');
// next();
// }
},{
path:'/b',
component:myB,
}
];
// 创建路由器对象router(声明路由器对象实例)
let router=new VueRouter({
// 声明配置路由对象
routes:routes,
// 切换路由模式
mode:'hash'
// mode:'history'
});
// 全局守卫
// 全局前置守卫
// router.beforeEach((to,from,next)=>{
// console.log(to,from,'全局前置守卫');
// next();
// });
// 全局后置守卫
// router.afterEach((to,from,next)=>{
// console.log(to,from,'全局后置守卫');
// });
// to:即将要进入的路由对象
// from:当前导航正要离开的路由对象
// next:function一定要调用该方法来触发后置守卫,跳转路由对应的页面
new Vue({
el:'#app',
// 3、注册路由对象(将路由实例对象导入vue实例对象)
// router:router,
router,
// 局部注册组件
components:{
'my-a':myA,
'my-b':myB
},
data:{
},
methods: {
},
})
</script>
</body>
</html>
面试题:实现页面跳转的方式?
a标签
<router-link>
编程式导航