一、起步
1、概念
Vue Router 是 Vue.js官方的路由管理器,主要用来做SPA(Single Page Application),单页面应用”
路由模式:
- hash:历史模式,不会制造页面刷新
- history:不会有历史,不会制造页面刷新
2、安装
npm install vue-router
yarn add vue-router
二、配置Router
1、搭建路由文件
位置:src/router/index.js
1、引用文件
import vue from 'vue'
import vueRouter from 'vue-router'
vue.use(vueRouter)
// 导入模板文件(用于公共路由)
import user from './modules/user'
import system from './modules/system';
// 导入公共页面(用于component)
import Layout from '@/layout/index.vue'
import Redirect from '@/views/redirect/redirect.vue'
import Page404 from '@/views/404/404'
// 定义动态路由
const dynamicRoutes= [
...user,
...system
]
// 定义公共路由
const getPublicRoutes = () => {
return [
{
path: '/',
name: 'Layout',
component: Layout,
meta: { title: 'layout' },
redirect: '/redirect',
children: [
{
path: '/redirect/:path*',
name: 'Redirect',
component: Redirect,
meta: { title: '重定向' }
},
{
path: '/404',
name: 'Page404',
component: Page404,
meta: { title: '404' }
}
]
},
{
path: '/login',
name: 'Login',
component: () => import('@/views/login/login.vue'),
meta: { title: '登录 ' }
},
{
path: '*',
redirect: '/404'
}
]
}
// 创建路由
const createRouter = (routes) => new VueRouter({
scrollBehavior: () => ({ y: 0 }),
routes: routes
});
const router = createRouter(getPublicRoutes());
// 重置路由
export const resetRouter = (routes) => {
const newRouter = createRouter(routes || getPublicRoutes());
router.matcher = newRouter.matcher;
};
导出,将Router对象传入到vue实例
export default router
2、配置路由权限控制
位置:src/router/router.js
作用:进行路由导航守卫配置, 通过VueX数据对登录者的状态进行判断
import AppConfig from "@/config/app-config"; // 导入全局配置
import router from "@/router/index";
import store from "@/store/index";
import NProgress from "nprogress"; // 引入 进度条:页面跳转时出现在浏览器顶部的进度条
import "nprogress/nprogress.css"; // 引入 进度条样式
NProgress.configure({ showSpinner: false }); // 禁用进度环
// 全局前置守卫
router.beforeEach((to, from, next) => {
NProgress.start()
const authorization = store.getters.authorization; // 拿到token值,判断是否登录
if(authorization ){ // 已登录
if (to.path === "/login") {
next("/");
NProgress.done();
} else {
next();
}
}else{ // 未登录
if (AppConfig.isWhitePath(to.path)) {// 在白名单内
next();
} else {// 不在白名单内
if (AppConfig.tabBlackPaths.indexOf(to.path) !== -1) { // 在黑名单中
next('/login')
} else {
next({
path: "/login",
query: { redirect: to.path, ...to.query }
});
}
NProgress.done();
}
}
})
// 全局后置守卫
router.afterEach(() => NProgress.done());
3、全局配置
地址:src/main.js
import vue from 'vue'
import router from '@/router/index.js'
vue.config.productionTip = false //阻止启动生产消息,常用作指令
new Vue({
el: '#app',
router,//挂载路由,把路由注入为Vue对象方便使用
render: h => h(App)
})
三、使用Router
1、路由跳转的五种方法
router-link
(声明式路由)
<router-link
:to="{name:'home', query: {id:1}}"
:tag="div"
active-class="router-link-active"
exact-active-class="router-link-active-class"
exact
event="click"
replace
append
>
</router-link>
// 字段详解
to: 用于指定跳转的路径
tag: 可以指定router-link标签渲染成什么html元素
active-class: 链接激活时使用的 CSS 类名。默认值可以通过路由的构造选项 linkActiveClass 来全局配置
exact-active-class: 链接被精确匹配的时候应该激活的 class。默认值可以通过路由的构造选项 linkExactActiveClass 来全局配置
exact: Boolean。是否开启严格匹配模式
event: 声明可以用来触发导航的事件,例如click、mouseover等
replace: Boolean。当点击时,会调用 router.replace() 而不是 router.push(),于是导航后不会留下 history 记录(无法返回上一页)
append: Boolean。设置 append 属性后,则在当前 (相对) 路径前添加基路径
router.push
(编程式路由)
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
// 如果提供了 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
this.$router.push()
(函数里面调用)
1. 不带参数
this.$router.push('/home')
this.$router.push({name:'home'})
this.$router.push({path:'/home'})
2. query传参
this.$router.push({name:'home',query: {id:'1'}})
this.$router.push({path:'/home',query: {id:'1'}})
// html 取参 $route.query.id
// script 取参 this.$route.query.id
3. params传参
this.$router.push({name:'home',params: {id:'1'}}) // 只能用 name
// 路由配置 path: "/home/:id" 或者 path: "/home:id" ,
// 不配置path ,第一次可请求,刷新页面id会消失
// 配置path,刷新页面id会保留
// html 取参 $route.params.id
// script 取参 this.$route.params.id
this.$router.replace()
(函数里面调用)
<template>
<el-button @click="handlerOne">页面一</el-button>
<el-button @click="handlerTwo">页面二</el-button>
</template>
<script>
export default {
methods:{
handlerOne():{
this.$router.replace("/pageTwo")
},
handlerTwo():{
this.$router.replace("/pageOne")
},
}
}
</script>
this.$router.go(n) ()
this.$router.go(n)
向前或者向后跳转n个页面,n可为正整数或负整数
ps : 区别
this.$router.push
跳转到指定url路径,并想history栈中添加一个记录,点击后退会返回到上一个页面
this.$router.replace
跳转到指定url路径,但是history栈中不会有记录,点击返回会跳转到上上个页面 (就是直接替换了当前页面)
this.$router.go(n)
向前或者向后跳转n个页面,n可为正整数或负整数
2、Params、Query的区别
query
可以用name、path来引入;parmas
使用name引入- 接收:
this.$router.query.name
和this.$router.params.name
query
类似于get,params
类似于post- 使用
query
传参在浏览器地址栏中会显示参数,params
不会显示,params传值相对安全 query
刷新后值还在,params
刷新后值没了
query传参:
this.$router.push({
name:'user',
path:'/user'
query:{
name:'张三',
id:'1'
}
})
name、path二选一
地址栏显示效果:`http://localhost:8080/user?name=张三&id=1`
刷新后显示效果:`http://localhost:8080/user?name=张三&id=1`
params传参:
this.$router.push({
name:'user',
params:{
name:'李四',
id:'2'
}
})
地址栏显示效果:`http://localhost:8080/user`
刷新后显示效果:`http://localhost:8080/user`,这时候params中没有参数
3、路由传参的四种方式
- router-link 路由传参
// 路由配置
{
path: '/a/:num',
name: A,
component: A
}
// 父组件
<router-link to = "/a/111"></router-link>
// 子组件
mounted () {
this.num = this.$route.params.num
}
地址栏中显示:`http://localhost:8080/#/a/111`
- $router.push实现路由传参
// 路由配置
{ path: '/d/:id', name: D, component: D }
// 父组件:
<button @click="deliverParams(123)">push传参</button>
methods: {
deliverParams (id) {
this.$router.push({
path: `/d/${id}`
})
}
}
// 子组件:
mounted () {
this.id = this.$route.params.id
}
地址栏中的显示: `http://localhost:8080/#/d/123`
- 通过路由属性中的name匹配路由,再根据params传递参数
// 路由配置: 路径后面不需要再加传入的参数,但是name必须和父组件中的name一致
{path: '/b', name: 'B', component: B}
// 父组件
<button @click="deliverByName()">params传参</button>
deliverByName () {
this.$router.push({
name: 'B',
params: {
sometext: '一只羊出没'
}
})
}
// 子组件
mounted(){
this.text = this.$store.params.sometext
}
// 地址栏显示:地址栏不会带有传入的参数,且再次刷新页面后参数会丢失
http://localhost:8080/#/b
- 通过query来传递参数
// 路由配置: 路径后面不需要再加传入的参数,但是name必须和父组件中的name一致
{ path: '/c', name: 'C', component: C }
// 父组件
<button @click="deliverQuery()">query传参</button>
deliverQuery () {
this.$router.push({
path: '/c',
query: {
sometext: '同学'
}
})
}
// 子组件
mounted(){
this.text = this.$store.query.sometext
}
// 地址栏显示
http://localhost:808/#/c?sometext='同学'
4、接收参数的三种方式:
1、this.$router.params
2、this.$router.query
3、使用props接收
// 需要在路由中配置:设置props为true
{
path:'/user',
name:'user',
components:()=>import('@/views/user.vue'),
props:{name:'张三',id:'1'}
}
// 在页面中
<template>
<div>
{{ name }}
{{ id }}
{{ this.$route.params.name }}
{{ this.$route.params.id }}
{{ this.$route.query.name }}
{{ this.$route.query.id }}
</div>
</template>
<script>
export default {
props:{
name:{
type:String,
default:'zs' //默认情况
},
id:{
type:Number,
default:'0' //默认情况
}
}
}
</script>
5、动态路由匹配
<template>
<div id="app">
<el-button @click="goPage1">方法一</el-button>
<el-button @click="goPage2">方法二</el-button>
</div>
</template>
<scirpt>
export default {
data(){
return{
mqId1:'1',
mqId2:'2'
}
},
methods:{
goPage1(){
this.$router.push({
path:`/filledIn/drgDetail`,
query: {
mqId: this.mqId1
}
})
},
goPage2(){
this.$router.push('/user/'+this.mqId2)
}
}
}
</script>
6、$route
、$router
的区别
//$router : 是路由操作对象,只写对象
//$route : 路由信息对象,只读对象
//操作 路由跳转
this.$router.push({
name:`argu`,
params:{
name:'xrw',
age:'123'
}
})
//读取 路由参数接收
this.name = this.$route.params.name;
this.age = this.$route.params.age;