VUE的路由(vue-router)
• 参考网址:https://router.vuejs.org/zh/
• Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌
• 路由:一个路径对应一个组件
• 一个简单的路由配置需要4步
• 创建组件
• 配置路由映射表
• 注册路由配置表
• 把路由挂在在根实例上
vue-router的使用方法
• HTML
• router-link:这个标签是路由的导航,会默认被渲染为一个a标签
• router-link里面可以写一些属性: to属性指定链接也就是要跳转的路由,to属性和路由映射表的path的属性值一样
• tag属性指定router-link渲染标签
• router-view: 是路由的出口,路由匹配到的组件将渲染到这个标签里,当组件切换时,组件的DOM元素删除
• JavaScript
• 一个简单的路由配置需要4步
• 创建组件
• 配置路由映射表
• 注册路由配置表
• 把路由挂在在根实例上
• vue-router中的方法
• 当每一个被路由渲染出来的组件上有一个$router属性,在这个属性的原型上有一些操作路由的方法
• push : 直接跳转到当前路径对应的路由上 push(路径)
• back : 回退到上一次的路由上
• go(number):可以往前可以往后回退后前进几个
路由的嵌套
• 二级路由不能直接配置到routes,应该找到它对应的以及路由,配置到其children属性上;
• 在组件路由配置是,对象中有children属性,属性值是一个数组,里面配置了子路由,路由中不需要加父路由路径地址,同时也不需要加"/",当子路由进行匹配式,会自动加上父路由和/到子路由的前面;
命名路由
• 在配置文件中加入name属性,然后可以用html的router-link标签的to属性匹配路由
<script>
let detail = {
template:"<div>详情页</div>"
};
let login = {
template:"<div>登录注册页</div>"
};
let home = {
data(){
return {
con:'首页'
}
},
methods:{
goList(){
console.log(this);
this.$router.go(-1)
}
},
template:"<div>{{con}}<button @click='goList'>去列表页</button></div>"
}
let person={
data(){
return {
con:'个人中心页'
}
},
template:"#list"
}
let routes =[
{path:"/allhome",component:home,name:"first"},
{path:"/allperson",component:person,children:[
{path:"detail",component:detail},
{path:"login",component:login}
]}
];
let router = new VueRouter({
routes:routes
})
let vm = new Vue({
el:"#app",
data:{
},
router
})
</script>
路由传参
动态传参
• 动态路由:路由传参;路径后面是一个:变量;这就是动态路由,也可以叫路由动态传参;会把id以属性方式放到$route的params属性上,属性值就是路由实际的路径值
• 特点
• 代码量少
• 由于动态路由渲染的是同一个子组件,所以子组件不再销毁,当然也不再创建,复用了之前的组件,性能高;但是生命周期的钩子函数也不再执行;
<body>
<div id="app">
<router-link to="/home/1">第1本</router-link>
<router-link to="/home/2">第2本</router-link>
<router-link to="/home/3">第3本</router-link>
<router-view></router-view>
</div>
<script src="../../node_modules/vue/dist/vue.js"></script>
<script src="../../node_modules/vue-router/dist/vue-router.js"></script>
<script>
let home = {
template:"<div>这是我喜欢的第{{$route.params.id}}本书</div>"
}
const router = new VueRouter({
routes: [{path:"/home/:id",component:home}]
})
let vm = new Vue({
el:"#app",
data(){
return {
}
},
router
})
</script>
</body>
</html>
query传参
• 在跳转网页时执行一个方法,使用push方法,并传一个参数,可以在跳转网页的$route.query中获得
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<router-link to="/home">第1本</router-link>
<router-link to="/list">第2本</router-link>
<router-view></router-view>
</div>
<script src="../../node_modules/vue/dist/vue.js"></script>
<script src="../../node_modules/vue-router/dist/vue-router.js"></script>
<script>
let home = {
methods: {
goList(){
this.$router.push({path:'/list',query:{id:100}})
}
},
template:"<div>首页<button @click='goList'>去列表</button></div>"
}
let list={
created(){
console.log(this.$route.query.id);
},
template:"<div>列表页</div>"
}
const router = new VueRouter({
routes: [
{path:"/home",component:home,name:"first"},
{path:"/list",component:list,name:"second"}
]
})
let vm = new Vue({
el:"#app",
data(){
return {
}
},
router
})
</script>
params方法传参
• 使用params必须得在to属性中用name属性
<div id="app">
<router-link :to="{name:'first'}">第1本</router-link>
<router-link :to="{name:'second'}">第2本</router-link>
<router-view></router-view>
</div>
<script src="../../node_modules/vue/dist/vue.js"></script>
<script src="../../node_modules/vue-router/dist/vue-router.js"></script>
<script>
let home = {
methods: {
goList(){
this.$router.push({name:"second",params:{id:500}})
}
},
template:"<div>首页<button @click='goList'>去列表</button></div>"
}
let list={
created(){
console.log(this.$route.params.id);
},
template:"<div>列表页</div>"
}
const router = new VueRouter({
routes: [
{path:"/home",component:home,name:"first"},
{path:"/list",component:list,name:"second"}
]
})
let vm = new Vue({
el:"#app",
data(){
return {
}
},
router
})
</script>
命名视图
• 有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar (侧导航) 和 main (主内容) 两个视图,这个时候命名视图就派上用场了。
• 没有name属性,会显示属性为default的组件
redirect 路由重定向
• 在配置路由中可以用redirect将路由路径重新定向
• 在配置路由中可以用redirect设置默认展示的组件
• redirect可以用名字设置,也可以用路径设置
• / 代表初始页,*代表全部报错的网页
<body>
<div id="app">
<router-link to="/home" tag="button">首页</router-link>
<router-link to="/list" tag="button">列表页</router-link>
<router-view></router-view>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script src="node_modules/vue-router/dist/vue-router.js"></script>
<script>
let home = {
template: "<div>首页内容</div>"
};
let list = {
template: "<div>列表页内容</div>"
};
let found = {
template: "<div>页面404</div>"
};
let routes = [{ path: "/", component: home }, { path: "/home", component: home }, { path: "/list", component: list }, { path: "/a", component: found }, { path: "*", redirect: "/home" }];
let router = new VueRouter({
routes
});
let vm = new Vue({
el: "#app",
router
})
</script>
路由的导航守卫
• 导航守卫:当切换导航时,会默认调用一些钩子函数,那么这些钩子函数就是导航的守卫;可以在进入这个导航或者离开这个导航时,在钩子函数中做一些事情
• 参数或查询的改变并不会触发进入/离开的导航守卫(比如动态传参)
• 如果全部的钩子函数都执行完了,那么导航的状态就是confirmed(确定的)
• 切换到另一个组件,组件是会销毁的
全局守卫
全局前置守卫(beforeEach)
• 全局的前置钩子函数,只要切换组件,就会执行
• 这个钩子函数可以用来写用户权限的校验
• 这个钩子函数有三个参数,第一个参数(一般写作to)为即将要进入的目标路由对象(到哪去),第二个参数(一般写作from)为当前导航要离开的路由(从哪来),第三个参数(一般写作next)为下一步,只有执行了第三个参数,才会继续执行下一个钩子函数
• 第三个参执行的不同情况
• next() :进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
• next(false) : 中断当前的导航。如果浏览器的URL改变了(可能是用户手动或者浏览器后退按钮),那么URL地址会重置到from(第二个参)路由对应的地址
• next('/')或者next({path:'/'}) :跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向next传递任意位置的对象,且允许设置诸如replace:true、name:'home'之类的选项以及任何用在router-link的to或router.push中的选项
• next(error) : 如果传入next的参数是一个error实例(报错信息),则导航会被终止且该错误会被传递给router.onError()注册过的回调
全局解析守卫(beforeResolve)
• 全局解析守卫在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫会被调用
• 参数与全局前置守卫相同
全局后置钩子函数(afterEach)
• 全局后置钩子不会接受next函数页不会改变导航本身,是路由切换以后执行的钩子函数
• afterEach只有前两个参
路由独享的守卫(beforeEnter)
• 路由独享守卫在路由配置上定义,在beforeEach和beforeRouteUpdate后执行
• 参数和beforeEach相同
组件内的守卫(在路由组件内定义)
beforeRouteEnter
• 这个钩子函数在进入路由组件,导航被确定之前调用
• 这个函数的this为window,因为当beforeRouteEnter执行前,组件实例还没有被创建。但是可以通过传一个回调给next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数(一般写作vm)
• 只有beforeRouteEnter支持给next传回调
• 参数和beforeEach相同
beforeRouteUpdate
• 在当前路由改变,但是该组件被复用时调用(如动态参数)
• 可以访问组件实例this
• 当beforeRoute执行的时候,只有三个全局钩子函数执行,其余的钩子函数都不执行(具体看例子)
• 参数和beforeEach相同
beforeRouteLeave
• 导航离开该组件对应路由时调用
• 可以访问组件实例this
• 这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以用next(false)来取消
• 参数和beforeEach相同
完整的导航解析流程
- 导航被触发
- 在失活的组件里调用离开守卫beforeRouteLeave
- 调用全局的beforeEach守卫
- 在重用的组件里调用beforeRouteUpdate守卫(2.2版本+)
- 在路由配置里调用beforeEnter
- 解析异步路由组件
- 在被激活的组件里调用beforeRouteEnter
- 调用全局的beforeResolve守卫(2.5版本+)
- 导航被确认
- 调用全局的afterEach钩子
- 触发DOM更新
- 用创建好的实例调用beforeRouteEnter守卫中传给next的回调函数