路由简介
1、简介
(1)路由就是一组key-value的对应关系
(2)路由要经过路由器的管理
2、路由工作原理简介:
(1)目的:为了实现导航区和展示区内容的切换
(2)Vue中的router代表路由,可以实现页面不全部刷新进行切换,根据不同的route规则展示不同的组件。
vue-router
路由基本使用
1、安装vue-router
注意:在vue2中要安装vue-router3,在vue3中要安装vue-router4。
安装vue-router3命令:npm i vue-router@3
2、应用插件:Vue.ues(VueRouter)
3、编写router配置项:
先创建router文件,然后建立index.js文件,并且在index.js文件中配置router
index.js
//该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../components/About.vue'
import Home from '../components/Home.vue'
//创建并暴露一个路由器
export default new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home
}
]
})
对应的main.js需要增加的代码:
//引入路由器
import router from './router'
Vue.config.productionTip = false
//应用插件
Vue.use(VueRouter)
区分路由组件与一般组件
路由组件:通过<router-view>
或<router-link>
放入组件内容,不用导入;
一般组件:通过components导入放入组件的内容。
一般开发时最好将路由组件和一般组件区分开来,所以在src中新建一个pages文件存放路由组件,目录结构如下:
路由嵌套(多级路由)
要实现的功能效果:
在Home路由中嵌套News和Message路由
1、在已有路由中的children中配置下级路由,
(1)index.js中的更改
import Message from '../page/Message.vue'
import News from '../page/News.vue'
//创建并暴露一个路由器
export default new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home,
children:[
{
path:'news', //子路由不加/
component:News
},
{
path:'message', //子路由不加/
component:Message
},
]
}
]
})
(2)在page文件中新建Message.vue和News.vue
Message.vue
<template>
<ul>
<li>
<a href="/message1">message0001</a>
</li>
<li>
<a href="/message2">message0002</a>
</li>
<li>
<a href="/message3">message0003</a>
</li>
</ul>
</template>
<script>
export default {
name:'Message'
}
</script>
News.vue
<template>
<ul>
<li>news001</li>
<li>news002</li>
<li>news003</li>
</ul>
</template>
<script>
export default {
name:'News'
}
</script>
2、注意在Home.vue中将router-link中to的路径写完整
Home.vue中template内容:
<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参数
要实现的效果:点击Message路由中的消息会产生不同的提示信息,效果如下图:
步骤:
1、在Message.vue中补充数据
2、新建Detail.vue
<template>
<ul>
<li>消息编号:{{this.$route.query.id}}</li>
<li>消息标题:{{this.$route.query.title}}</li>
</ul>
</template>
<script>
export default {
name:'Detail',
}
</script>
3、query的两种写法,一般推荐对象写法
<li v-for="p in messageList" :key="p.id" >
<!-- 跳转路由并携带query参数,to的字符串写法 -->
<!-- <router-link active-class="active" :to="`/home/message/detail?id=${p.id}&title=${p.title}`">{{p.title}}</router-link> -->
<!-- 跳转路由并携带query参数,to的对象写法 -->
<router-link :to="{
path:'/home/message/detail',
query:{
id:p.id,
title:p.title
}
}">
{{p.title}}
</router-link>
</li>
命名路由
给路由起名字来访问路由,不需要写完整路径。
用途:
1、index.js中添加路由的名字
2、在App.vue中通过导入路由名字来访问路由
路由的params参数
1、在控制台中可以找到params:
2、步骤:
(1)配置占位符:
index.js
//创建并暴露一个路由器
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/:id/:title',
component:Detail,
}
]
},
]
}
]
})
(2)传递参数
Message.vue中
<template>
<ul>
<li v-for="p in messageList" :key="p.id" >
<!-- 跳转路由并携带params参数方法一 -->
<router-link active-class="active" :to="`/home/message/detail/${p.id}/${p.title}`">{{p.title}}</router-link>
<!-- 跳转路由并携带params参数方法二 -->
<!-- 注意:这里必须用name属性来寻找路由,不能用path属性 -->
<!-- <router-link :to="{
name:'xiangqing',
params:{
id:p.id,
title:p.title
}
}">
{{p.title}}
</router-link> -->
</li>
<hr />
<router-view></router-view>
</ul>
</template>
(3)接收参数
Detail.vue中
<template>
<ul>
<li>消息编号:{{$route.params.id}}</li>
<li>消息标题:{{$route.params.title}}</li>
</ul>
</template>
路由props配置
(补充)回调函数:定义了但函数中没有调用,最终却执行了的函数。
作用:让路由组件更加方便的收到参数
步骤:
1、在index.js的detail配置中添加props属性
2、在Detail.vue中添加具体的props属性
方法一:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件
index.js
Detail.vue
<template>
<ul>
<li>消息编号:{{$route.params.id}}</li>
<li>消息标题:{{$route.params.title}}</li>
<li>a:{{a}}</li>
</ul>
</template>
<script>
export default {
name:'Detail',
props:['a']
}
</script>
方法二:props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给Detail组件
index.js
Detail.vue
<template>
<ul>
<li>消息编号:{{id}}</li>
<li>消息标题:{{title}}</li>
</ul>
</template>
<script>
export default {
name:'Detail',
props:['id','title']
}
</script>
方法三:props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件(此时不用写占位符)
index.js
Message.vue注意修改为query方式
<li v-for="p in messageList" :key="p.id" >
<!-- 跳转路由并携带params参数方法一 -->
<!-- <router-link active-class="active" :to="`/home/message/detail/${p.id}/${p.title}`">{{p.title}}</router-link> -->
<!-- 跳转路由并携带params参数方法二 -->
<!-- 注意:这里必须用name属性来寻找路由,不能用path属性 -->
<router-link :to="{
name:'xiangqing',
query:{
id:p.id,
title:p.title
}
}">
{{p.title}}
</router-link>
</li>
Detail.vue
<template>
<ul>
<li>消息编号:{{id}}</li>
<li>消息标题:{{title}}</li>
</ul>
</template>
<script>
export default {
name:'Detail',
props:['id','title']
}
</script>
router-link中的replace属性
1、浏览器的两种模式
(1)模式一:push模式
每次点击都会产生新的页面。历史记录是一个栈结构,有一个指针(指针在栈顶),指向当前页面,如下图所示:
(2)模式二:replace模式
不保存历史记录,替换当前栈顶的记录
2、开启replace模式
在router-link标签中添加replace属性:replace="true"
,如下图所示:
<router-link :replace="true" class="list-group-item" active-class="active" :to="{name:'guanyu'}">About</router-link>
编程式路由导航
作用:不借助<router-link>
实现路由跳转,让路由跳转的更加灵活。因为<router-link>
最后会转换为<a>
标签,但如果我们想要编写<button>
标签或者实现开机过三秒跳转页面的效果就不能通过<router-link>
来实现,但可以借助编程式路由导航来实现。
1、应用一:不借助<router-link>
通过点击实现push和replace的操作
效果:在消息列表中添加查看组件,通过点击按钮实现显示下表内容,效果如下图
Message.vue中的修改
①在<template>
中添加如下语句
<button @click="pushShow(p)">push查看</button>
<button @click="replacehShow(p)">replace查看</button>
②在<script>
中的Message对象中添加方法:
methods:{
pushShow(m){
this.$router.push({
name:'xiangqing',
query:{
id:m.id,
title:m.title
}
})
},
replacehShow(m){
this.$router.replace({
name:'xiangqing',
query:{
id:m.id,
title:m.title
}
})
}
}
2、应用二:添加前进后退键
效果图:点击前进键返回之前的页面,点击后退键回到下一个界面,具体效果如下图:
Banner.vue中的修改:
<template>
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header"><h2>Vue Router Demo</h2></div>
<button @click="forward()">前进</button>
<button @click="back()">后退</button>
</div>
</template>
<script>
export default {
name:'Banner',
methods:{
forward(){
this.$router.forward();
},
back(){
this.$router.back();
}
}
}
</script>
小结:借助$router组件我们可以轻松实现编程式,接下来我们输出一下看看 $router 中的内容。
输出代码,在Home.vue中的mounted()函数进行查看。
mounted() {
console.log('输出一下:',this.$router);
}
$router 内容:
缓存路由组件
1、作用:让不展示的路由组件保持挂载,不被销毁。
2、具体实现:
<!-- 注意,这里的include包含的使组件名!!! -->
<keep-alive include="News">
<router-view></router-view>
</keep-alive>
两个新的生命周期钩子
作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态。
actived
激活时触发
deactivated
失活时出发
应用:
(1)需求:当切换到news界面时激活news路由组件,可以让文字透明度产生渐变;当离开news界面时关闭news路由组件并且将news文本框中的文字缓存起来以便于下次进入news界面还能看到文字。
(利用上一节的缓存路由组件可以缓存news中的文字内容)
News.vue
<template>
<ul>
<li :style="{opacity}">欢迎学习Vue</li>
<li>news001</li><textarea></textarea>
<li>news002</li><textarea></textarea>
<li>news003</li><textarea></textarea>
</ul>
</template>
<script>
export default {
name:'News',
data() {
return {
opacity:1
}
},
//引入两个路由独有的生命周期钩子
//激活,想看的时候被激活
activated() {
console.log('News组件被激活了')
this.timer = setInterval(() => {
this.opacity -= 0.01
if(this.opacity <= 0) this.opacity = 1
},16)
},
//失活,不想看的时候失活
deactivated() {
console.log('News组件失活了')
clearInterval(this.timer);
}
}
</script>
补充:第三个生命周期钩子(在TodoList中学过)
$nextTick() 功能:当操作完DOM并把功能放入页面后再调用 $nextTick()
生命周期函数:在vm特定的生命周期vm帮我们调用的函数成为生命周期函数。
路由守卫
作用:保护路由的安全
全局前置路由守卫
1、作用:全局前置路由守卫–每次初始化时被调用,路由切换之前被调用
(重点:路由切换前,路由切换前,路由切换前被调用!!!)
2、具体使用:
index.js
(1)在被限制的路由组件中的meta中配置isAuth属性
(2)
router.beforeEach((to,from,next)=>{
//to 表示要去哪里
//from 表示从哪里来
//next() 表示放行
if(to.meta.isAuth){ //判断是否需要鉴权,这里注意要在被限制的路由组件中的meta中配置isAuth属性
if(localStorage.name == 'bushizhiwu'){
next()
}
else{
alert('学校名称不对,无权限查看!');
}
}
else{
next()
}
})
后置路由守卫
1、作用:每次初始化时被调用,路由切换之后被调用
2、应用:切换页面时更改页面的标题
(1)给每个路由组件配置一个标题
在meta中配置title属性
meta:{title:'关于'}
(2)index.js中配置后置路由
//全局后置路由守卫--每次初始化时被调用,路由切换之后被调用
router.afterEach((to,from)=>{
console.log('后置路由守卫',to,from)
document.title = to.meta.title || '硅谷系统'
})
独享路由守卫
1、作用:访问某个路由组件前调用,初始化某个路由组件时被调用。
(注意:独享路由守卫只有前置,没有后置)
2、应用:
(1)需求:保证新闻主页中必须是用户名为’bushizhiwu’这个用户才能访问,并且在访问其他路由时没有影响。
(2)实现:
组件内路由守卫
1、作用:分为进入守卫,离开守卫两个;
进入守卫,通过路由规则时,进入该组件时被调用;
离开守卫,通过路由规则时,离开该组件时被调用。
2、使用方法:
//通过路由规则,进入该组件时被调用
//这里说的路由规则要注意,因为我也可以将它作为一个普通的组件进行导入,此时不遵守路由规则
beforeRouteEnter(to,from,next) {
console.log('About--beforeRouteEnter',to,from)
if(to.meta.isAuth){
if(localStorage.getItem('name') == 'bushizhiwu'){
next()
}else{
alert('学校名称不对,无权限查看')
}
}else{
next()
}
},
//通过路由规则,离开该组件时被调用
beforeRouteLeave(to,from,next) {
console.log('About--beforeRouteLeave',to,from)
next()
}
history模式与hash模式
1、对于一个url来说,什么是hash值?
#及其后面的内容就是hash值,如下图所示:
2、hash值不会包含在HTTP请求中,即:hash值不会带给服务器。
3、两种模式:
(1)hash模式:
- 地址中永远带着#号,不美观
- 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法
- 兼容性较好
(2)history模式
- 地址干净、美观
- 兼容性和hash模式相比略差
- 应用部署上线时,解决刷新页面服务端404的问题
4、项目上线:用vue写好项目后需要生成纯js,html,css构成的文件用于部署在其他服务器上完成上线。
所以需要我们对项目进行打包,生成一个新的文件,命令:npm run build
,执行完命令后会生成一个dist文件夹可以让我们部署在服务器上。