一、什么是路由?
路由Router,描述了不同的请求和对应的处理函数之间的映射关系
(表示了根据映射规则,分发用户请求到不同的业务模块,执行业务流程的过程)
二、为什么要使用路由?
1、动态组件切换页面,无法通过浏览器url路径切换
2、动态组件设置自定义属性和监听自定义事件比较繁琐
3、页面中出现二级页面时,动态组件的切换方式不太好
(因为动态组件实现页面切换,不论是开发中,还是再实际使用中,代码过于繁琐,同时对于系统资源消耗较大,所以要使用路由来完成页面切换的功能)
三、路由基础
1、下载安装
创建vue项目(在指定的文件夹地址栏处,输入cmd,回车,在黑窗口输入以下命令)
vue create app01
进入项目,执行命令,安装路由模块
首先进入项目文件夹
cd app01
下载路由模块
npm i vue-router@3 -S
(注意:@后面的数字是指的安装的路由的版本是3版本的,因为我安装的vue是2版本的,根据适配性,路由安装3版本的)
2、快速入门
(1)创建路由视图组件
创建对应的文件夹
(2)配置路由映射规则
创建规则配置文件:src/router/index.js
// 1、导入依赖
import Vue from 'vue';
import VueRouter from 'vue-router';
// 2、挂载路由
Vue.use(VueRouter);
// 3、导入组件对象
import Main from '../pages/Main'
import Reg from '../pages/Reg'
import Login from '../pages/Login'
import Home from '../pages/Home';
import List from '../pages/List';
import Ucenter from '../pages/Ucenter';
import About from '../pages/About';
// 4、创建映射规则
const routes = [
{
name: 'main',
path: '/main',
component: Main
},{
name: 'about',
path: '/about',
component: About
}
]
},
{
name: 'reg',
path: '/reg',
component: Reg
}, {
name: 'login',
path: '/login',
component: Login
}
]
// 5、创建路由对象
const router = new VueRouter({
routes,
linkActiveClass: 'active',//设置被点击时导航栏的样式
});
// 6、导出路由
export default router;
(3)在指定的显示路由页面的地方,编辑App.vue,添加显示路由组件的代码:
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "App",
components: {},
};
</script>
<style>
</style>
(4)添加、注册、挂载路由规则
编辑运行入口模块,src/main.js,添加路由对象
import Vue from 'vue'
import App from './App.vue';
import router from './router/index'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app')
(5)拓展:添加路由导航链接
编辑App.vue,添加路由导航链接
<ul>
<li><router-link :to="{ name: 'home' }">首页</router-link></li>
<li><router-link :to="{ name: 'menu' }">菜单管理</router-link></li>
<li><router-link :to="{ name: 'role' }">角色管理</router-link></li>
<li><router-link :to="{ name: 'user' }">用户管理</router-link></li>
</ul>
3、导航高亮
点击了导航链接,页面中展示了对应的路由视图组件!(通过给导航链接添加上特定的样式,让用户知道当前路由视图组件对应的是哪个导航?)
(1)直接修饰样式:router-link-active
编辑App.vue,添加高亮样式,在style中给类名router-link-active设置样式
.router-link-active{
display: block;
background: orangered;
color: white;
}
(2)自定义修饰样式。(为避免使用公共的类名出现问题,自行定义高亮样式)
先在index.js中路由实例中,定义linkActiveClass属性为active(active即为自定义的类名。后面要保持一致)
const router = new VueRouter({
routes,
linkActiveClass: 'active'
});
//在设置导航对应的vue文件中,写样式
.active {
background-color: rgba(199, 190, 190, 0.348);
}
4、严格匹配
vueRouter路由的路径匹配方式,是按照正则表达式的方式匹配的,最常见的路径写法就是字符串的完整写法,但是某些情况下会出现一些路径互相包含的问题,比如
<ul>
<li><router-link to="/">LOGO</router-link></li>
<li><router-link to="/main">首页</router-link></li>
<li><router-link to="/login">登录</router-link></li>
<li><router-link to="/reg">注册</router-link></li>
</ul>
<!--这种首页、注册和登录链接中都会包含LOGO链接,最直接导致的问题就是多个导航同时高亮 -->
解决办法:给可能出现问题的链接添加exact属性
<ul>
<li><router-link to="/" exact>LOGO</router-link></li>
<li><router-link to="/main">首页</router-link></li>
<li><router-link to="/login">登录</router-link></li>
<li><router-link to="/reg">注册</router-link></li>
</ul>
5、路由别名
当用户希望某个组件可以同时通过多个路径进行访问时,可以使用别名的方式实现。使用alias配置别名。
编辑index.js文件
const routes = [
{
path: '/main',
alias: '/', // 配置别名
component: Main
},
]
6、路由重定向
用户访问某个路径时,程序将用户访问的路径重新指向了另一个路径进行访问,这个过程称为路由重定向。
修改路由映射规则:src/router/index.js,添加重定向配置
const routes = [
{
path: '/', // 用户请求路径
redirect: '/main' // 程序重定向路径
},
{
path: '/main',
component: Main
},
....
]
7、路由匹配模式
路由匹配模式,也成为路由历史记录,主要用于切换底层路由匹配方式的。
主要通过官方文档进行了解,hash模式是默认的路由匹配模式。
(1)两种匹配模式语法:
编辑:src/router/index.js,配置匹配模式
const router = new VueRouter({
routes, // 路由映射规则
// mode: 'hash', // 路由匹配模式,默认hash模式
mode: 'history' // 路由另一种匹配模式,底层history.pushState保障页面不刷新
})
(2)两种匹配模式对比
hash模式 | history模式 |
---|---|
路径中带有#符号 | 路径中没有#符号 |
(3)两种匹配模式场景
hash模式 | history模式 |
---|---|
一般用于开发中 | 一般用于测试和发布后使用 |
页面不会重新加载(浏览器的特性) | 页面不会重新加载(代码功能实现) |
无需多余配置 | 需要配置404路由 |
开发中打包测试使用 | 发布并交付测试运维时打包使用 |
8、命名路由
项目一旦开发完成,后期可能会遇到各种需求进行变更,其中包括一种变更方式:变更请求路径。如果直接修改每个书写的路径,难免会遗漏或出现错误。为降低出错率,使用命名路由。
(1)配置路由映射规则,给路由定义name选项(命名路由)
...
const routes = [
...
{
name: 'login', // 命名路由
// path: '/login', //变更前的路径
path: '/signin', // 变更请求路径的需求
component: Login
},
...
]
(2)页面组件中,通过命名路由实现页面切换
<!-- 原始切换方式,直接通过路径切换 -->
<router-link to="/home">首页</router-link>
<!-- 新的切换页面方式,通过命名路由切换 -->
<router-link :to="{name: 'login'}">登录</router-link>
9、命名视图
需求描述,项目中不同的页面显示的内容区分不同的内容区域,如:
vueRouter中,针对一个页面中同时显示不同的页面组件内容,提供了一种命名视图的操作
<!-- 回忆插槽 -->
<template>
<slot name="header"></slot> <!-- 具名插槽 -->
<div class="body">
<slot></slot> <!-- 匿名插槽 -->
</div>
</template>
<!-- VueRouter 路由实现中,提供了一种命名视图 -->
<template>
<!-- 命名视图 -->
<router-view name="header"></router-view>
<div class="body">
<!-- 匿名路由视图,默认路由视图-->
<router-view></router-view>
</div>
</template>
编辑路由规则:
...
const routes = [
{
path: '/',
redirect: '/main'
},
{
path: '/main',
components: {
header: MainHeaderVue,
default: Main
}
},
{
path: '/login',
components: {
header: CommHeaderVue,
default: Login
}
},
{
path: '/reg',
components: {
header: CommHeaderVue,
default: Reg
}
}
]
10、嵌套路由
项目中经常出现二级页面跳转的情况,如:
vuerouter中提供了二级路由的配置方式,通过路由规则的children属性二级嵌套路由
1、配置路由映射规则
const routes = [
{..},
{..},
{
path: '/main',
components: {
header: MainHeaderVue,
default: Main
},
children: [ // 配置当前路由规则下的二级路由
{
name: 'home',
path: 'home',
component: Home
},
{
name: 'list',
path: 'list',
component: List
},
{
name: 'ucenter',
path: 'ucenter',
component: Ucenter
},
{
name: 'about',
path: 'about',
component: About
}
]
}
]
(2)编辑Main.vue,添加二级路由的展示视图
<template>
<div class="main-container">
<!-- 二级路由 路由视图 -->
<router-view></router-view>
<nav>
<!-- 命名路由方式,实现动态跳转-->
<ul>
<li><router-link :to="{name: 'home'}">首页</router-link></li>
<li><router-link :to="{name: 'list'}">列表</router-link></li>
<li><router-link :to="{name: 'ucenter'}">用户</router-link></li>
<li><router-link :to="{name: 'about'}">我的</router-link></li>
</ul>
</nav>
</div>
</template>
11、编程式导航
vuerouter给每个页面组件,提供了两个路由对象
$route:当前路由对象,描述了本次请求路由对象
$router:全局路由对象, 描述了整个路由规则
页面组件中可以通过$router实现在代码中完成页面跳转,称为编程式导航
编辑查看用户资料页面,添加编程式导航的代码,
<template>
<div class="detail-container">
<h3>查看用户资料页面</h3>
<button @click="goBack">后退</button>
<button @click="goForward">前进</button>
<button @click="pushHome">回到首页push</button>
<button @click="replaceHome">回到首页replace</button>
</div>
</template>
<script>
export default {
created() {
// 查看路由对象
console.log(this.$router, "this.$router全局路由对象")
console.log(this.$route, "this.$route当前路由对象")
},
methods: {
goBack() {
// 编程式导航:后退,访问上一个历史记录
this.$router.back()
},
goForward() {
// 编程式导航:前进,访问下一个历史记录
this.$router.forward()
},
pushHome() {
// 编程式导航:保留访问记录的情况下跳转到指定路由
// this.$router.push('/home')
this.$router.push({name: 'home'})
},
replaceHome() {
// 编程式导航:不保留访问记录的情况下跳转到指定路由
this.$router.replace({name: 'home'})
}
}
}
</script>
<style>
</style>
route当前路由对象")
},
methods: {
goBack() {
// 编程式导航:后退,访问上一个历史记录
this.KaTeX parse error: Expected 'EOF', got '}' at position 19: …ter.back() }̲, goForward…router.forward()
},
pushHome() {
// 编程式导航:保留访问记录的情况下跳转到指定路由
// this.
r
o
u
t
e
r
.
p
u
s
h
(
′
/
h
o
m
e
′
)
t
h
i
s
.
router.push('/home') this.
router.push(′/home′)this.router.push({name: ‘home’})
},
replaceHome() {
// 编程式导航:不保留访问记录的情况下跳转到指定路由
this.$router.replace({name: ‘home’})
}
}
}