1.路由
路由是一组映射关系,多个路由需要路由器管理,在web开发中路由可以帮助实现SPA应用, vue官方提供了vue-router来管理这些路由;
注意:vue-router现在的默认版本是4,而vue-router4只能用于vue3,所哟我们需要指定版本安装vue-router3才能在vue2中使用;
基本使用?
- 安装vue-router,npm i vue-router
- 使用vue-router,在main.js中先导入vue-router然后Vue.use(vueRouter)
- 编写router配置项:在src下新建router文件夹,新建index.js用于管理route
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中的vue实例中配置router属性
//引入Vue import Vue from 'vue' //引入App import App from './App.vue' //引入VueRouter import VueRouter from 'vue-router' //引入路由器 import router from './router' //关闭Vue的生产提示 Vue.config.productionTip = false //应用插件 Vue.use(VueRouter) //创建vm new Vue({ el:'#app', render: h => h(App), router:router })
随后在html中使用router-link标签实现路由跳转(router-link最后也会变成一个a标签);router-view标签实现指定位置渲染(作用和插槽差不多,但是他是一整个组件的dom结构都放进去,也方便很多)
<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>
一些注意点
-
路由组件通常存放在
pages
文件夹,一般组件通常存放在components
文件夹。 -
通过切换,“隐藏”了的路由组件,默认是被销毁掉的,需要的时候再去挂载。
-
每个组件都有自己的
$route
属性,里面存储着自己的路由信息。 -
整个应用只有一个router,可以通过组件的
$router
属性获取到。
2.多级路由(嵌套路由)
使用children属性来配置多级路由
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中没有“/”!
实现跳转?
默认记得写完整路径
<router-link to="/home/news">News</router-link>
如果路由组件有name,则可以使用name来跳转
<!--简化前,需要写完整的路径 -->
<router-link to="/home/message/detail">跳转</router-link>
<!--简化后,直接通过名字跳转 -->
<router-link :to="{name:'xiangqing'}">跳转</router-link>
3.如何跳转时传递参数
3.1 通过query
和ajax一样,?id=xxx&name=xxx,但也可以使用对象的形式(把router-link的to写成对象)
<!-- 跳转并携带query参数,to的字符串写法 -->
<router-link :to="/home/message/detail?id=666&title=你好">跳转</router-link>
<!-- 跳转并携带query参数,to的对象写法 -->
<router-link
:to="{
path:'/home/message/detail',
query:{
id:666,
title:'你好'
}
}"
>跳转</router-link>
对象的写法比较的好读;
如何接收?
使用路由组件自带的$route对象
$route.query.id
$route.query.title
3.2 通过params
稍微会复杂一点,也和ajax中的一样
首先需要在路由配置的时候使用占位符表示要接收params参数以及他的名称
{
path:'/home',
component:Home,
children:[
{
path:'news',
component:News
},
{
component:Message,
children:[
{
name:'xiangqing',
path:'detail/:id/:title', //使用占位符声明接收params参数
component:Detail
}
]
}
]
}
然后在router-link标签中的to路径中写要传的数据
<!-- 跳转并携带params参数,to的字符串写法 -->
<router-link :to="/home/message/detail/666/你好">跳转</router-link>
<!-- 跳转并携带params参数,to的对象写法 -->
<router-link
:to="{
name:'xiangqing',
params:{
id:666,
title:'你好'
}
}"
>跳转</router-link>
记得如果要使用to的对象写法的话,只能使用name配置,不能使用path
如何接收?
同query一样,在route中拿。
3.3 通过props
在配置路由的时候加上props属性;
{
name:'xiangqing',
path:'detail/:id',
component:Detail,
//第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件
props:{a:900}
//第二种写法:props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给Detail组件
props:true
//第三种写法:props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件
props(route){
return {
id:route.query.id,
title:route.query.title
}
}
}
第二种写法的意思就是,本来我们通过params来给子路由传递参数时需要借助$route对象来拿到数据,使用第二种写法之后我们可以直接在子路由组件中配置props拿到参数,如下所示:
export default {
name:'Detail',
props:['id','title']
}
4.路由控制浏览器的页面前进后退
router-link默认是push模式,每次切换路由时会追加历史记录,因而我们可以在页面操作前进后退;
4.1 replace
我们可以指定router-link使用replace模式,replace开启之后每次切换路由会替代上一条记录;
如何开启?
<router-link replace .......>News</router-link>
4.2 编程式路由导航
不借助router-link来实现路由的跳转,相对于router-link会更加灵活,比如说我们需要在一个按钮上添加一个click事件来跳转路由,这个时候就无法使用router-link,我们就需要使用编程式路由导航。
如何实现?
//$router的两个API
this.$router.push({
name:'xiangqing',
params:{
id:xxx,
title:xxx
}
})
this.$router.replace({
name:'xiangqing',
params:{
id:xxx,
title:xxx
}
})
this.$router.forward() //前进
this.$router.back() //后退
this.$router.go(1) //可前进也可后退,传入整数就是往前1,负数就是倒退
5.keep-alive
keep-alive使得组件被切换时不会被销毁,继续被挂载
如何使用?
<keep-alive include="News">
<!-- 只有include中的会被缓存,include里面的是组件名(.vue文件里的name) -->
<router-view></router-view>
</keep-alive>
// 当有多个组件需要keepalive时
<keep-alive :include=["News","Message"]>
<router-view></router-view>
</keep-alive>
6.路由组件的新生命周期钩子
-
activated()
路由组件被激活时触发。 -
deactivated()
路由组件失活时触发。
7.路由守卫
路由守卫可以对路由跳转进行权限控制,它分为全局守卫、独享守卫和组件内守卫三种;
他们有三个参数,分别是to、from和next;
- to:从哪里出发,是一个对象,里面有路径、参数、meta(路由原信息)等数据;
在配置路由的时候可以加上meta配置项,当我们需要路由守卫进行数据判断时候就可以用to.meta.xxx直接使用
- from:到哪里,也是一个对象;
- next:当决定放行时调用next();
7.1 全局守卫
全局守卫会在路由器初始化的时候以及每次切换路由时的前/后执行,取决于是前置还是后置守卫;
//全局前置守卫:初始化时执行、每次路由切换前执行
router.beforeEach((to,from,next)=>{
// to 是去哪里的路由对象 n
console.log('beforeEach',to,from)
if(to.meta.isAuth){ //判断当前路由是否需要进行权限控制
if(localStorage.getItem('school') === 'atguigu'){ //权限控制的具体规则
next() //放行
}else{
alert('暂无权限查看')
// next({name:'guanyu'})
}
}else{
next() //放行
}
})
//全局后置守卫:初始化时执行、每次路由切换后执行
router.afterEach((to,from)=>{
console.log('afterEach',to,from)
if(to.meta.title){
document.title = to.meta.title //修改网页的title
}else{
document.title = 'vue_test'
}
})
7.2 独享守卫
独享守卫需要在配置路由的时候就给他配置上,配置内函数逻辑和全局守卫一模一样,但是独享守卫没有后置守卫。
7.3 组件内守卫
//进入守卫:通过路由规则,进入该组件时被调用
beforeRouteEnter (to, from, next) {
},
//离开守卫:通过路由规则,离开该组件时被调用
beforeRouteLeave (to, from, next) {
}