highlight: a11y-dark
Vue--路由的使用
路由的基本使用
在这里我做了一个极其简陋的页面,大家不要见怪哈。
主要分分为三个部分,头部的标题,左面的导航区,右面的内容展示区。
我们点击左面的导航,右面展示区就会显示对应的内容。现在我们来使用路由来完成这个功能。
第一步 安装vue-router
由于我的脚手架是2.0版本的,所以使用的路由就安装3.0的
npm i vue-router@3
第三步 引入并使用
在main.js中 引入并使用router插件
import Vue from 'vue'
import App from './App.vue'
//引入vue-router
import VueRouter from 'vue-router'
import store from './store/index'
//使用vue-router
Vue.use(VueRouter)
Vue.config.productionTip = false
new Vue({
render: h => h(App),
store,
beforeCreate(){
Vue.prototype.$bus=this//安装全局总线
},
router:Router
}).$mount('#app')
第三步配置路由信息
我们在src中新建一个文件夹名为router,里面创建一个index.js用来配置路由信息。
首先需要将vue-router引入,之后创建并暴露路由规则。路由的路径与跳转的组件写在routes中。他是一个数组,里面书写配置信息。
path:路径
component:此路径的组件
import VueRouter from 'vue-router'
import FirstDemo from '../pages/FirstDemo'
import SecondDemo from '../pages/SecondDemo'
import ThirdDemo from '../pages/ThirdDemo'
export default new VueRouter({
routes:[
{
path:'/first',
component:FirstDemo
},
{
path:'/second',
component:SecondDemo
},
{
path:'/third',
component:ThirdDemo
},
]
})
在书写完路由信息后,将他引入在main.js中import Router from './router/index'
这样路由规则就配置好了。就可以使用了。
第四步 实现切换
我们知道在普通页面中,我们实现页面的跳转是靠a标签实现的,在这里我们要实现路由跳转用的是router-link这个标签,他与a类似,但又有区别。使用路由跳转可以做到页面无刷新更新页面内容。具体代码如下:
<router-link to="/first" class="nav" active-class="active">第一个导航</router-link>
<router-link to="/second" class="nav" active-class="active">第二个导航</router-link>
<router-link to="/third" class="nav" active-class="active">第三个导航</router-link>
to表示要跳转的地址,这个我们在配置路由链接的时候就写好了,active-class可以设置被点击时的高亮显示。
接下来就是设置路由跳转后,页面在哪里显示了,使用<router-view></router-view>标签,完整代码如下:
<template>
<div>
<router-link to="/first" class="nav" active-class="active">第一个导航</router-link>
<router-link to="/second" class="nav" active-class="active">第二个导航</router-link>
<router-link to="/third" class="nav" active-class="active">第三个导航</router-link>
<div class="content">
<router-view></router-view>
</div>
</div>
</template>
页面效果
这就完成了路由的基本使用。
我们来总结一下:
- 下载
- 引入
- 在src下新建router文件夹,在里面新建index.js用来书写路由配置。
- 实现切换,使用router-link建立连接,使用router-view显示内容。
这就是路由的基本使用啦。
多级路由
多级路由在实践中也很常见,其实会了二级路由也就会了多级路由。在这里我就演示一个二级路由吧。
我们在第一个导航内容区域在设置两个导航项
接下来配置路由信息,我们看到是在第一个导航内容中设置导航,所以得在第一个导航区的路由信息里配置子路由信息。使用children关键字。
{
path:'/first',
component:FirstDemo,
children:[
{
path:'news',
component:NewsDemo
},
{
path:'weather',
component:WeatherDemo
}
]
},
里面书写的内容和一级路由一模一样,但是要记得,path中不要再写‘/’。切记切记。 接下来写router-link与router-view
<template>
<div>
第一个导航的内容
<ul>
<router-link to='/first/news' active-class="active">新闻</router-link>
<router-link to='/first/weather' active-class="active">天气</router-link>
</ul>
<div class="">
<router-view></router-view>
</div>
</div>
</template>
这里有一个注意点,在to中一定要写完整的路由信息,否则会无法正常跳转。最后显示效果如下:
这就是二级路由,其实多级路由就是一直往里写Children.
我们来总结一下
- 配置路由信息,记得不要写'/'
- 写连接,写展示标签。(你们懂我意思哈)
携带query参数
现在有一个需求,点击一个消息,在他下下面显示出详细消息。
我们在路由链接里将消息的详细内容,通过query参数传递给组件。
<template>
<div>
<ul>
<router-link
:to='`/second/news?id=${p.id}&title=${p.title}`' //在这里携带query参数 在?后开始书写,用&符号拼接
v-for="p in personList" :key="p.id"//用v-for遍历
>
{{p.title}}
</router-link>
</ul>
<router-view></router-view>
</div>
</template>
<script>
export default {
name:'SecondDemo',
data(){
return {
personList:[
{id:'001',title:'第一条消息'},
{id:'002',title:'第二条消息'},
{id:'003',title:'第三条消息'},
]
}
}
}
</script>
<style scoped>
a{
text-decoration: none;
color: black;
margin: 10px;
}
</style>
这样我们就把query参数传递给了要展示的组件中。在组件中我们接收一下。
<template>
<div>
<ul>
<li>{{$route.query.id}}</li>
<li>{{$route.query.title}}</li>
</ul>
</div>
</template>
完成!
但是吧,这种写法如果要携带的参数过于多,这种写法看上去就很难受了,所以还有另外一种写法。对象写法。这样写看起来就很好了。
<router-link
v-for="p in personList" :key="p.id"
:to="{
path:'/second/news',
query:{
id:p.id,
title:p.title
}
} "
>
{{p.title}}
</router-link>
路由命名
在前面我们写路径的时候发现,如果路径太长的话,很不方便观察,容易写错。这时就需要我们的路由命名了。我们给详细详情这个路径命名。
{
path:'/second',
component:SecondDemo,
children:[
{
name:'xiangq',
path:'news',
component:DetilDemo
}
]
},
这时候我们在传递参数时就可以写name,不用写path了。路由命名适用于路径特别长的时候,很方便。
<router-link
v-for="p in personList" :key="p.id"
:to="{
name:'xiangq',
query:{
id:p.id,
title:p.title
}
}">
携带params参数
路由还可以携带params参数。我们做一个和携带query参数类似的案例。
携带params参数的代码如下
<template>
<div>
第三个导航内容
<ul>
<router-link
:to='`/third/stunent/${s.id}/${s.sno}`'//携带params参数
v-for='s in stuList' :key='s.id'>
{{s.name}}
</router-link>
</ul>
<router-view></router-view>
</div>
</template>
<script>
export default {
name:'ThirdDemo',
data(){
return{
stuList:[
{id:'001',sno:'192100906',name:'张三'},
{id:'002',sno:'192100908',name:'李四'}
]
}
}
}
</script>
携带params参数相对来说比较简单,直接在/ 后写参数即可,但是需要在路由配置里,声明一下参数。
{
path:'/third',
component:ThirdDemo,
children:[
{
path:'stunent/:id/:sno',
component:StudentDemo
}
]
},
接收一下数据
<template>
<ul>
<li>{{$route.params.id}}</li>
<li>{{$route.params.sno}}</li>
</ul>
</template>
<script>
export default {
name:'StudentDemo'
}
</script>
和携带query参数一样,携带params参数也有对象写法。
<router-link
:to="{//params参数的对象写法
name:'stu',
params:{
id:s.id,
sno:s.sno
}
}"
v-for='s in stuList' :key='s.id'>
{{s.name}}
</router-link>
props配置
在前面,我们接收参数的时候,我们老写这样的代码。
<ul>
<li>{{$route.params.id}}</li>
<li>{{$route.params.sno}}</li>
</ul>
<ul>
<li>{{$route.query.id}}</li>
<li>{{$route.query.title}}</li>
</ul>
这样其实不太符合vue的风格,要尽可能的简化{{}}里面的内容。这时我们就需要props配置了。props要写在路由配置里。peops配置有很多写法,在这里我就介绍函数式写法。
{
path:'/third',
component:ThirdDemo,
children:[
{
name:'stu',
path:'stunent/:id/:sno',
component:StudentDemo,
props($route){//props配置
return{
id:$route.params.id,
sno:$route.params.sno
}
}
}
]
},
配置完成之后需要在对应的组件接收,
<template>
<ul>
<li>{{id}}</li>
<li>{{sno}}</li>
</ul>
</template>
<script>
export default {
name:'StudentDemo',
props:['id','sno']
}
</script>
我们看到,使用props配置可以更方便的接收参数。
编程式路由导航
什么是编程式路由导航,我们先不管这个概念,在上面的路由中,我们实现路由跳转都是靠router-link这个标签,它类似于a标签,我们点击他,他才会跳转,如果有一个按钮,有一个图片想要实现路由跳转怎么办,这时就需要编程式路由导航了。
我们现在有两个按钮,如下,点击他实现路由跳转。
我们给这两个按钮绑定点击事件,然后调用路由器上两个api。
<template>
<div>
<button @click="eat">去吃饭</button>
<button @click="sleep">去睡觉</button>
<router-view></router-view>
</div>
</template>
<script>
export default {
name:'ForthDemo',
methods:{
eat(){
this.$router.push({
path:'/four/eat'
})
},
sleep(){
this.$router.push({
path:'/four/sleep'
})
}
},
}
</script>
<style>
button{
margin: 10px;
}
</style>
在绑定的点击事件中,我调用了push这个方法,它里面传递配置对象,可以传递路径,query参数,params参数(当然不止这些),在这里为了简单我就不写了。效果如下
我们还可以在这个组件一挂载,调用一个定时器,2秒后实现路由跳转,这样就不用点击了,
mounted(){
setTimeout(()=>{
this.$router.push({
path:'/four/eat'
})
},2000)
}
还有一个api replace他与push的区别就是push会产生历史记录,而replace不会。使用方法完全一样。大家感兴趣可以试试。
缓存路由组件
我们首先要知道,我们点击一个路由组件,他会加载。当点出去时,他就会被销毁。当我们在组件中输入一些东西时,点到另外一个组件,再回来时输入的内容就不在了,怎么解决这个问题呢?我们可以使用缓存路由组件,在<router-view></router-view>外层使用keep-alive标签包裹。
<keep-alive include="EatDemo,SleepDemo">
<router-view></router-view>
</keep-alive>
在include里写要缓存的组件名,这样这个问题就解决了。
路由组件特有的钩子
activated与deactivated是路由组件特有的钩子。activated是当一个路由组件被加载时被调用,deactivated是当一个路由组件被销毁时被调用。但是需要注意的是,这两个钩子需要配合缓存路由组件以一起使用keep-alive,没有keep-alive是无法触发的。
<template>
<div>
欢迎来到餐厅
<input type="text" name="" id="">
</div>
</template>
<script>
export default {
name:'EatDemo',
activated(){
console.log('eat组件被调用');
},
deactivated() {
console.log('eat组件被销毁');
},
}
</script>
全局前置路由守卫
什么是路由守卫呢?其实就是相当于保安,在进入这个路由前,进行判断,看是否满足我们的要求,满足则放行,不满足就不放行。全局路由守卫就是在配置文件中设置路由守卫。 beforeEach是全局前置路由守卫,他里面传一个函数,函数里有三个参数。
router.beforeEach((to,from,next)=>{
console.log(to,from ,next);
next()
})
我们将这三个参数输出看一下
前两个都是对象,最后一个是函数。第一个对象表示要去的信息。第二个对象标识从哪里来的信息。next函数就是用来放行的函数。
现在来实现一个功能,点击第一个导航中的新闻与天气,不放行,点击其他的导航都放行。我们在新闻组件与天气组件的配置里写一个配置,写在meta中,isAuth为真表示不放行。
{
name:'xinwen',
path:'news',
component:NewsDemo,
meta:{
isAuth:true
}
},
{
name:'tianqi',
path:'weather',
component:WeatherDemo,
meta:{
isAuth:true
}
}
全局路由守卫:
router.beforeEach((to,from,next)=>{
if(to.meta.isAuth===true){
alert('不放行')
}else{
next()
}
})
这样就实现了功能。
那么全局前置什么时候被调用呢?是在初始化-每次路由切换之前。
全局后置路由守卫
全局后置路由守卫是在初始化-每次路由切换之后调用,我们可以利用全局后置路由守卫实现切换组件后,给页面标题换成我们想要的。
首先给每个路由配置里添加meat配置,里面写title。之后利用全局后置路由守卫实现点击切换后,换标题。
router.afterEach((to,from)=>{
console.log(from);
document.title=to.meta.title || '啦啦啦'
})
我们看到全局后置守卫里的回调函数只有两个参数。这样功能就实现了。
路由守卫还有两种,一种是独享路由守卫,他只守卫一个路由,写在某个组件的路由配置里就好了。
beforeEnter:(to,from,next)=>{
}
还有一种是组件路由守卫
//通过路由规则,进入该组件时被调用
beforeRouteEnter(to,from,next){
console.log(to,from,next);
},
//通过路由规则,离开该组件时被调用
beforeRouteLeave(to,from,next){
console.log(to,from,next);
}
他们写在组件中就可以了、