目录
一、路由 vue-router
(一)路由与路由器
(二)vue-router 理解
(三)SPA 理解
(四)路由 理解
(五)小案例
1.About.vue
2.Home.vue
3.index.js
4.App.vue
5.main.js
(六)使用步骤
(七)注意点
二、嵌套路由/多级路由
一、路由 vue-router
(一)路由与路由器
路由器能让多台设备同时上网 每个网线插口都能对应一个设备
路由器 的英文名是 router
路由器上的插口就相当于 key 我们的每个设备相当于 value 一共四个接口
那路由就是 route
key1 + value1 => 路由 route
key2 + value2 => 路由
key3 + value3 => 路由
key4 + value4 => 路由
路由就是一组 key-value 的对应关系
多个路由需要经过路由器管理
我们编程中的路由和生活中的不一样 我们编程中的路由是为了 实现 SPA 应用(单页面应用)
之前的应用是 我们写很多网页然后得来回跳转 这就是多页面应用 不太好来回跳很烦
单页面就一个页面比较好 然后里面有导航区 和展示区 点击导航区的导航然后实现显示区的内容发生变化,但是页面没跳转,左上角没转圈,路径也能跟着变化
怎么实现的页面变化然后路径也发生变化的呢
点击导航区中的班级管理 然后我们路径中多了 /class
原来是 我们的vue 中 router 能监测到 我们路径中 /class 这样的路由
路由规则是 router /class => 班级组件 如果监测到 /class 就展示 班级组件
/class 就相当于是key 班级组件相当于 value
(二)vue-router 理解
vue 的一个插件库 专门实现 SPA 应用 npm i vue-router
Vue.use()使用
(三)SPA 理解
单页面 Web 应用,整个应用只有一个完整的页面 index.html
点击页面中的导航链接不会刷新页面 只会做页面的局部更新
数据要通过 ajax 请求获取
(四)路由 理解
一个路由就是一组映射关系
key 是路径 value 是function 或 component
路由分类 :
1.后端路由:
理解;value 是 funciton 用于处理客户端提交的请求
工作过程:服务器接收到一个请求时,根据请求路径找到匹配的函数来处理请求,返回响应数据。
2.前端路由
理解:value 是 component用于显示页面内容
工作过程:当浏览器路径改变时,对应的组件就会显示
(五)小案例
1.About.vue
<template>
<h2>我是About的内容</h2>
</template>
<script>
export default {
name: "About",
};
</script>
<style>
</style>
2.Home.vue
<template>
<h2>我是Home的内容</h2>
</template>
<script>
export default {
name: "Home",
};
</script>
<style>
</style>
3.index.js
import VueRouter from 'vue-router'
import About from '../components/About'
import Home from '../components/Home'
export default new VueRouter({
routes: [
{
path: '/about',
component: About
},
{
path: '/home',
component: Home
},
]
})
4.App.vue
<template>
<div>
<div class="row">
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header"><h2>Vue Router Demo</h2></div>
</div>
</div>
<div class="row">
<div class="col-xs-2 col-xs-offset-2">
<div class="list-group">
<!-- <a class="list-group-item" href="./about.html">About</a>
<a class="list-group-item active" href="./home.html">Home</a> -->
<router-link class="list-group-item" active-class="active" to="/about">About</router-link>
<router-link class="list-group-item" active-class="active" to="/home">Home</router-link>
</div>
</div>
<div class="col-xs-6">
<div class="panel">
<div class="panel-body">
<router-view></router-view>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "app",
};
</script>
5.main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import router from './router/index'
Vue.use(VueRouter)
Vue.config.productionTip = false
new Vue({
el: '#app',
render: h => h(App),
router: router
})
(六)使用步骤
1.安装 vue-router 命令 npm i vue-router
2.使用插件 Vue.use(VueRouter)
3.编写 router 配置项
就是在 src 文件夹中创建一个 router 文件夹 然后里面创建一个 index.js 文件里面配置路由
import VueRouter from 'vue-router'
import About from '../components/About'
import Home from '../components/Home'
export default new VueRouter({
routes: [
{
path: '/about',
component: About
},
{
path: '/home',
component: Home
},
]
})
main.js 中引入 router 然后内部 写上 router:router
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import router from './router/index'
Vue.use(VueRouter)
Vue.config.productionTip = false
new Vue({
el: '#app',
render: h => h(App),
router: router
})
4.实现切换
然后我们写切换组件的内容我们来到 app 组件中 得用一个特殊的标签 就是 router-link 里面再用一个 to 来表示 切换到的标签
router-link 里面能自动转换成 a 标签 所以我们得用人家的router-link 标签
<router-link class="list-group-item" to="/about">About</router-link>
<router-link class="list-group-item active" to="/home">Home</router-link>
5.指定显示内容
最后指定显示的内容到页面上该标签的位置
<router-view></router-view>
(七)注意点
路由组件 不用我们自己写 <zujian/> 而是靠路由规则而显示的标签叫做路由组件
这些路由组件 单独放一个文件夹中 不放 conponents 中 放在 pages 中
切换显示的组件的时候 不显示的组件是被销毁了
路由组件上 有两个属性 一个是 $route 是路由属性是我们配置的每个组件都不一样
另一个是 $router 是路由器 每个网页只能由一个路由器 是所有组件共有的
二、嵌套路由/多级路由
点击导航栏 然后显示的页面中又显示 一个导航栏 再点击 路径中出现 /school/student 的类似情况就是多级路由
在路由中再配置其它的路由就是多级路由
如下是一级路由
export default new VueRouter({
routes: [
{
path: '/about',
component: About
},
{
path: '/home',
component: Home
},
]
})
多级路由就是在我们已经配置的路由里面再配置子路由,因为可能不止一个子路由 就用数组对象的形式,注意里面的 path 不用加斜杠 因为网页在寻找的时候已经自动帮我们配置了斜杆
export default new VueRouter({
routes: [
{
path: '/about',
component: About
},
{
path: '/home',
component: Home,
children:[
{
path:'news',
component: News,
},
{
path: 'message',
component: Message,
}
]
},
]
})
在写按钮时 跳转时 路径名得补全 /home/news
<template>
<div>
<h2>Home组件内容</h2>
<div>
<ul class="nav nav-tabs">
<li>
<router-link class="list-group-item" active-class="active" to="/home/news">News</router-link>
</li>
<li>
<router-link class="list-group-item" active-class="active" to="/home/message">Message</router-link>
</li>
</ul>
<router-view></router-view>
</div>
</div>
</template>
三、路由传参
(一)query 参数
跳转路由并携带 query 参数,有两种写法
跳转的时候带着参数 我们用 ajax 请求 携带query 参数实现路由传参 不一直用多级路由来写,要不然组件太多
1.to 的字符串写法
里面是字符串 然后里面套一个 模板字符串 然后 用${ } 传入数据 :是使用 js 语法来解析
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
<router-link :to="`/home/message/detail?id=${m.id}$title=${m.title}`">{{m.title}}</router-link>
</li>
</ul>
<hr>
<router-view></router-view>
</div>
</template>
我们在子路由中通过 $route.query.id $route.query.title 就能读取我们传入 detail 的数据
2.to 的对象写法
把 to 里面的东西写成对象的写法 有两个参数 第一个是我们要跳转的目标,第二个是我们要传入的参数,里面配置参数即可
<router-link
:to="{
path: '/home/message/detail',
query: {
id: m.id,
title: m.title,
},
}">
{{ m.title }}
</router-link>
我们在子路由中通过 $route.query.id $route.query.title 就能读取我们传入 detail 的数据
用这两句 接收一下就行
(二)params 参数
也是 ajax 请求中的,我们在 路由配置时 用两个占位符占两个 params 传入参数变量
路由中声明接收 params 参数
children:[
{
name:'xiangqing',
path: 'detail/:id/:title',
component: Detail,
}
]
1.to 的字符串写法
直接拼进去
配置选择路由路径的时候 直接 在 detail 后面写上 /加变量的形式 就能传入数据了
<router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{m.title}}</router-link>
我们在子路由中通过 $route.params.id $route.params.title 就能读取我们传入 detail 的数据
2.to 的对象写法
和 query 参数的对象写法中类似,对象里面的第二个配置项变成了 params 而且 第一个属性不能用 path 必须用 name !!!
<router-link
:to="{
name: 'xiangqing',
params: {
id: m.id,
title: m.title,
},
}">
{{ m.title }}
</router-link>
我们在子路由中通过 $route.params.id $route.params.title 就能读取我们传入 detail 的数据
(三)detail 读取路由中参数
我们在子路由中通过 $route.params.id $route.params.title 读取我们传入 detail 的数据
我们在子路由中通过 $route.query.id $route.query.title 读取我们传入 detail 的数据
但是这样很麻烦 如果要传入很多 我们得一个个写一遍 我们也能 通过计算属性简化写法,但是每个参数我们都得写一遍 也挺麻烦 所以我们需要路由中的一个全新的配置项 props
1.值为对象(用的非常少)
该对象中的所有 key-value 都会以props 的形式传给 Detail 组件
path: 'message',
component: Message,
children:[
{
name:'xiangqing',
path: 'detail/:id/:title',
component: Detail,
props:{a:1,b:'hello'}
}
]
组件中也得用 props 接收然后就能用这个a b 两个属性了
props: ["a", "b"],
2.值为布尔值
如果 值为 true 就会把路由中 组件收到的所有 params 参数 以props 的 形式传给 Detail 组件
不会理会 query 参数
path: 'message',
component: Message,
children:[
{
name:'xiangqing',
path: 'detail/:id/:title',
component: Detail,
// props:{a:1,b:'hello'}
props:true
}
]
接收一下
props: ["id", "title"],
3.值为函数
有一个回调函数 里面会返回给我们 $route 我们把 query 类型数据返回 实现简写
path: 'message',
component: Message,
children: [
{
name: 'xiangqing',
path: 'detail',
component: Detail,
// props:{a:1,b:'hello'}
// props:true
props($route) {
return {
id:$route.query.id,
title:$route.query.title
}
}
}
]
改成 query 方式发送
<router-link
:to="{
name: 'xiangqing',
query: {
id: m.id,
title: m.title,
},
}">
{{ m.title }}
</router-link>
四、命名路由
就是给路由起名字 给谁起名字 就在哪个路由上 加一个名字属性
可以在跳转的时候简化代码
给路由起名字 就是加一个配置属性 name
export default new VueRouter({
routes: [
{
name:'guanyu',
path: '/about',
component: About
},
{
path: '/home',
component: Home,
children:[
{
path:'news',
component: News,
},
{
path: 'message',
component: Message,
children:[
{
name:'xiangqing',
path: 'detail',
component: Detail,
}
]
}
]
},
]
})
然后给我们跳转传参的时候 可以把 path 配置项 改成 name 配置项 然后里面写上我们要传入的路由名,就能实现 简化路由的路径写法
<router-link
:to="{
name: 'xiangqing',
query: {
id: m.id,
title: m.title,
},
}">
{{ m.title }}
</router-link>
五、<router-link> 的 replace 属性
路由对浏览器中浏览记录的影响
浏览器中的前进后退按钮 是根据浏览器记录 进行使用的
使用 router-link 标签设计的 按钮 点击都会留下记录
有两种模式
(一)push 模式
保存浏览器记录 是栈的形式 点击按钮会依次将记录留在栈中 是 push 模式(默认模式)
指针指向浏览器最后的记录
点击回退 指针依次向下指
(二)replace 模式
替换当前的记录
另一种模式 replace 模式 点击新的链接 然后上一条的存在栈中的 浏览记录被删除
在 代码中 router-link 标签 中加入 一个 replace 属性就能开启 replace 模式
<router-link replace class="list-group-item" active-class="active" to="/home/news">News</router-link>
最后会回到 没被删除的记录
六、编程式路由导航
不借助 router-link 实现路由跳转 让路由跳转更灵活
不用 router-link 标签 实现路由选择 因为 router-link 最后只能转换成 a 标签,别的就不行了,比如按钮
我们就用一个新的方法来实现
如果是按钮我们先绑定一个点击事件 pushShow(m) 我们在方法中写一个函数 也叫 pushShow(m)
oush 方式跳转
pushShow(m) {
this.$router.push({
name: "xiangqing",
query: {
id: m.id,
title: m.title,
}
});
},
replace 方式跳转
replaceShow(m) {
this.$router.replace({
name: "xiangqing",
query: {
id: m.id,
title: m.title,
}
});
},
this.$router.go(数字) 里面是正数 跳转往前跳转
如果是负数就往后跳转
七、缓存路由组件
让不展示的路由组件保持挂载,不被销毁
如果写在 keep-alive 里面的组件都将被缓存 如果标签里面写了 inlcude=“News” 就指明了缓存的对象不是所有都缓存,只缓存里面的 News 缓存的名字是组件名 就是我们组件中写的第一个属性 name
<keep-alive incluede="News">
<router-view></router-view>
</keep-alive>
如果要缓存多个组件 那就写成数组的形式 先规定里面使用 js 中的规则 加一个冒号 即可
<keep-alive :incluede=["News","message"]>
<router-view></router-view>
</keep-alive>
八、新的声明周期钩子
路由组件独有的声明周期钩子
一个是激活的 另一个是失活的 两个钩子 当组件展示到我们眼前时就调用激活的函数
当组件被切走的时候 失活的周期就调用了
activated(){
},
deactivated(){
}
正常我们想写一个 文字循环减少透明度的格式,我们在 mounted 和 beforeDestoryed 两个声明周期写 但是我们我们前面实现对这个组件实现了缓存 会导致计时器关闭不了的情况
beforeDestroy() {
clearInterval(this);
},
mounted() {
this.timer = setInterval(() => {
this.opacity -= 0.01;
if (this.opacity <= 0) this.opacity = 1;
}, 16);
},
所以我们得用这两个声明周期钩子 就能成功解决了 显示的时候就显示 不显示的时候就关闭
activated() {
console.log('显示')
this.timer = setInterval(() => {
this.opacity -= 0.01;
if (this.opacity <= 0) this.opacity = 1;
}, 16);
},
deactivated() {
clearInterval(this.timer);
},
九、路由守卫
保护路由的安全就是给访问者设置权限
(一)前置路由守卫
全局前置路由守卫
在初始化和切换路由之前进行调用下面的函数
能把所有的东西都给拦住
函数内部有三个参数 to from next 一个是出发的路由 一个是目的路由 next 是放行的意思
然后在里面加上跳转权限就行
router.beforeEach((to, from, next) => {
console.log(to, from)
if (to.path === '/home/news' || to.path === '/home/message') {
if (localStorage.getItem('school') === 'xuexiao') {
next()
}
}else{
next()
}
})
export default router
但是第一个判断 条件太长 我们能在路由中加一个属性,我们加一个布尔属性就行 判断路由是否用判断路由是否需要 判断权限
我们得添加在 meta 中的属性中 比如叫 isAuth 是否授权
哪个路由需要判断权限 就给哪个路由加这个属性
{
name: 'guanyu',
path: '/about',
component: About,
meta: {
isAuth: true
}
},
然后代码就能简化一下
router.beforeEach((to, from, next) => {
console.log(to, from)
if (to.meta.isAuth) {
if (localStorage.getItem('school') === 'xuexiao') {
next()
}
} else {
next()
}
})
export default router
(二)后置路由守卫
在初始化和切换路由之后进行调用下面的函数
后置路由守卫 函数中没有 next 参数,因为已经切换成功了 不需要再判断是否切换了
router.afterEach()
router.afterEach((to, from) => {
document.title = to.meta.title || '硅谷系统'
})