一、创建路由
路由router/index.js
// 1 引入vue和vue-router
import Vue from 'vue';
import VueRouter from 'vue-router';
// 2 通过 Vue.use() 明确地安装路由功能
Vue.use(VueRouter);
/*
* 3 定义一些路由(即一个对象代表一个路由,都存放在数组routes中,也可以由外部导入)
* 每个路由都需要映射一个组件(即一个path对应一个component)
* 其他配置项包括name redirect meta等等
*/
const routes = [
{
// 会拼接到地址栏, 名字是自定义的('/'代表页面默认打开时的路由)
path: '/',
// 路由重定向(即只要到该路由就会被重定向到某路由,此处为'/home',所以此处无需映射组件)
redirect: '/home'
},
{
// 路由路径(当地址栏显示/home时,app.vue中的router-view便显示Home.vue的内容)
path: '/home',
// 路由名称(路由跳转时可以通过path,也可以通过name)
name: 'home',
// 组件懒加载(即处于此路由时才会导入该组件,而不是一开始就导入组件,利于性能优化)
// 也可以由其他文件直接导入
component: () => import('../views/Home.vue'),
// 默认显示子路由one
redirect: '/home/one',
// 路由的子路由(子路由的出口即router-view是需要写在其父级路由中的)
children:[
// 写法1,不加'/', 即代表'/home/list'
{path: 'one', component: () => import('../views/One.vue')},
// 写法2,加'/', 就需要写完整路由,也代表'/home/list'
{path: '/home/two', component: () => import('../views/Two.vue')}
],
// 路由源信息(按需使用)
meta: {
title: '主页',// 标题
icon: 'el-icon-s-home',// 图标
roles: ['admin', 'editor'],// 路由权限时使用
keepAlive: true,// 组件缓存时使用
}
}
];
// 4 创建路由实例
const router = new VueRouter({
// history模式地址栏不会显示#号,hash模式会显示#号,默认值是hash
mode: 'history',
routes
});
// 解决重复点击同一个路由时,控制台出现报错问题
// 报错内容:Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation
const VueRouterPush = VueRouter.prototype.push
VueRouter.prototype.push = function push (to) {
return VueRouterPush.call(this, to).catch(err => err)
}
VueRouter.prototype.replace = function replace (to) {
return VueRouterPush.call(this, to).catch(err => err)
}
// 5 导出路由实例
export default router
二、路由出口
一级路由的出口一般在app.vue中
<template>
<div id="app">
<router-view />
</div>
</template>
二级及以上路由的出口,一般是在其父级路由相对应的组件内部
<!-- 如一级路由home的子路由出口是在Home.vue的内部 -->
<template>
<div>
我是home页面
<main>
<!-- home子路由的出口 -->
<router-view />
</main>
</div>
</template>
<script>
export default {
name: 'Home',
};
</script>
三、路由跳转
路由的跳转方式有两种,一种是声明式,一种是编程式(常用)
1、声明式路由(通过html标签跳转)
必传参数
<!--
to 必传参数,表示指定跳转的路径:
1、字符串形式,如'/home/one'命名的路由(必须在router/index.js中有);
2、对象形式,如{ path: '/home/one', query: { id: 1 } }(query是可传递的参数)
注:路径必须是完整路径,否则如果写成'home/one'的类型,会直接拼接在当前路径的后面
-->
<router-link to="/home/one">one</router-link>
<router-link to="/home/two">two</router-link>
其他参数
<!--
1、tag 可选参数
表示使用什么标签来渲染
默认值是a,也可以是div、button等
2、replace 可选参数
表示是否使用replace方法来跳转
默认是false,表示使用push方法来跳转
3、append 可选参数(不推荐使用)
表示是否将to的值追加到当前的路径后面
默认是false
4、active-class 可选参数
表示当前路由匹配时的class
默认是router-link-active
5、exact-active-class 可选参数
表示当前路由完全匹配时的class
默认是router-link-exact-active
6、event 可选参数
表示触发跳转的事件
默认是click
-->
<router-link
to="/home/one"
tag="button"
replace="true"
append="false"
active-class="active"
exact-active-class="exact-active"
event="click"
>one</router-link>
2、编程式路由(通过js跳转)
常用的跳转方式
// 封装一个函数,通过事件调用即可
methods: {
goOne() {
// 1、push (跳转到指定的url,在history中添加记录)
// this.$router.push('/home/one')
// this.$router.push({ path: '/home/one' })
// this.$router.push({ path: '/home/one', query: { a: 1 } })
// this.$router.push({ name: 'HomeOne' })
// this.$router.push({ name: 'HomeOne', params: { a: 1 } })
// 2、replace重定向(跳转到指定的url,不在history中添加记录)
this.$router.replace('/home/one');// 推荐写法
// this.$router.replace({ path: '/home/one' })
// this.$router.replace({ path: '/home/one', query: { a: 1 } })
// this.$router.replace({ name: 'HomeOne' })
// this.$router.replace({ name: 'HomeOne', params: { a: 1 } })
}
}
其他跳转方式
this.$router.forward(); // 前进
this.$router.back(); // 后退
this.$router.go(); // 向前或向后跳转n个页面(n/-n)
四、路由传参
具体的写法在上面路由跳转时已说明,此处主要说明params和query的区别以及如果接收参数
1、参数接收
this.$route.params.id
this.$route.query.id
2、query和params的区别
1、搭配方式不同:query通常搭配path使用、params通常搭配name使用;
2、地址栏是否显示:query地址栏显示参数,params,地址栏不显示参数;
3、刷新是否造成数据丢失:query传值页面刷新也存在,params一刷新就没了(解决方案:在配置路由时加入占位符)
五、动态路由
在path配置一个字段“:name”,它表示此字段是动态的。此时不管是路径'/home/two/Tom',还是'/home/two/John’,或者是其他的,都会跳转到此路由。
router/index.js
{
path: '/home/two/:name',
component: () => import('../views/Two.vue')
},
跳转
const name = 'xxx'; // name是动态变化的
this.$router.replace('/home/one/'+name);
六、路由导航守卫
1、全局导航守卫
router/index.js
// 全局导航守卫(即在路由跳转前后做一些事情)
// 1.全局前置守卫
router.beforeEach((to, from, next) => {
// 1.1 判断是否需要登录
if (to.meta.requireAuth) {
// 1.1.1 判断是否登录
if (store.state.token) {
next();
} else {
// 1.1.2 未登录则跳转到登录页面
next({
path: '/login',
// 1.1.3 将跳转的路由path作为参数,登录成功后跳转到该路由
query: {redirect: to.fullPath}
})
}
} else {
next();
}
// 1.2 判断是否需要权限
if (to.meta.roles) {
// 1.2.1 判断是否有权限
if (store.state.roles.some(role => to.meta.roles.includes(role))) {
next();
} else {
// 1.2.2 无权限则跳转到401页面
next({
path: '/401',
// 1.2.3 将跳转的路由path作为参数,登录成功后跳转到该路由
query: {redirect: to.fullPath}
})
}
} else {
next();
}
});
// 2.全局后置守卫(后置守卫没有next参数)
router.afterEach((to, from) => {
// 2.1 设置标题
document.title = to.meta.title;
// 2.2 设置面包屑
store.commit('setBreadcrumb', to);
});
2、路由独享守卫
路由独享守卫,在进入该路由前执行的函数,可以用来判断是否有权限进入该路由,如果没有权限则跳转到其他路由。
{
path: '/home',
component: () => import('../views/Home.vue'),
beforeEnter: (to, from, next) => {
next();
}
},
3、组件内导航守卫
组件内导航守卫,只在当前组件生效,父子组件互不影响
export default {
name: 'Home',
// 导航守卫
beforeRouteEnter(to, from, next) {
console.log('beforeRouteEnter')
next()
},
beforeRouteUpdate(to, from, next) {
console.log('beforeRouteUpdate')
next()
},
beforeRouteLeave(to, from, next) {
console.log('beforeRouteLeave')
next()
},
methods: {
}
};
本文详细介绍了Vue.js中的路由创建,包括引入和安装Vue Router、定义路由、创建路由实例以及路由出口的设置。接着讲解了路由跳转的声明式和编程式方法,以及如何传递参数。动态路由和路由参数的使用也被提及,特别是params和query的区别。最后,文章阐述了路由导航守卫的概念,包括全局、路由独享和组件内的导航守卫,用于控制路由跳转时的权限和行为。



1442

被折叠的 条评论
为什么被折叠?



