Vue基础25
- 路由
- 编程式路由导航
- Home.vue(去掉两个router-line的replace)
- HomeMessage.vue
- Banner.vue
- 总结
- 缓存路由组件
- Home.vue
- HomeNews.vue
- HomeMessage.vue
- 总结
- 两个新的生命周期钩子
- HomeNews.vue
- HomeMessage.vue
- Home.vue
- 总结
- 全局路由守卫
- 路由前置守卫
- src/router/index.js
- 路由后置守卫及用户鉴权问题
- src/router/index.js
- 总结
- 独享路由守卫
- src/router/index.js
- 总结
- 组件内路由守卫
- src/router/index.js(改了about的用户鉴权)
- About.vue
- 总结
路由
编程式路由导航
Home.vue(去掉两个router-line的replace)
<template><div><h1>我是Home的内容</h1><br><div class="btn-group" role="group" aria-label="..."><router-link type="button" class="btn btn-default" active-class="active" to="/home/news">News</router-link><router-link type="button" class="btn btn-default" active-class="active" to="/home/message">Message</router-link></div><br><br><router-view></router-view></div>
</template><script>export default {name: "Home",/*mounted(){console.log("Home组件被挂载了")window.homeRoute=this.$routewindow.homeRouter=this.$router},beforeDestroy() {console.log("Home组件被销毁了")}*/}
</script><style scoped lang="less">
</style>
HomeMessage.vue
<template><div><button @click="goTest(2)">go查看测试(前进2步)</button><ul>
<!-- 跳转路由并携带params参数,to的字符串的写法--><li v-for="m in messageList" :key="m.id">
<!-- <router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{m.title}}</router-link>--><!-- 跳转路由并携带params参数,只能使用名字跳转,to的对象的写法--><router-link :to="{name:'xiangqing',query:{id:m.id,title:m.title}}">{{m.title}}</router-link><button @click="pushShow(m)">push查看</button><button @click="replaceShow(m)">replace查看</button><button @click="goTest(-3)">go查看测试(后退3步)</button><br></li></ul><hr><router-view></router-view></div>
</template><script>export default {name: "HomeMessage",data(){return{messageList:[{id:"001",title:"消息001"},{id:"002",title:"消息002"},{id:"003",title:"消息003"},]}},methods:{pushShow(m){console.log(this.$router)this.$router.push({name:'xiangqing',query:{id:m.id,title:m.title}})},replaceShow(m){this.$router.replace({name:'xiangqing',query:{id:m.id,title:m.title}})},goTest(value){this.$router.go(value)}}}
</script><style scoped>
.active{color: black;
}
</style>
Banner.vue
<template>
<div><h1>Vue Router Demo</h1><button @click="back()">后退</button><button @click="forward()">前进</button><br><br>
</div>
</template><script>export default {name: "Banner",methods:{back(){this.$router.back()},forward(){this.$router.forward()}}}
</script><style scoped>
h1{border-bottom: 1px solid #ccc;
}
</style>
总结
- 作用:不借助<router-link>实现路由跳转,让路由跳转更加灵活
- 具体编码:
//$router的两个API
this.$router.push({name:'xiangqing',query:{id:m.id,title:m.title}})this.$router.replace({name:'xiangqing',query:{id:m.id,title:m.title}})this.$router.back() //后退
this.$router.forward() //前进
this.$router.go(3) //可前进也可后退
- 补充一个$router的api:go
go函数的参数表示浏览器历史记录前进/后退几步(正数为前进,负数为后退)
缓存路由组件
Home.vue
<template><div><h1>我是Home的内容</h1><br><div class="btn-group" role="group" aria-label="..."><router-link type="button" class="btn btn-default" active-class="active" to="/home/news">News</router-link><router-link type="button" class="btn btn-default" active-class="active" to="/home/message">Message</router-link></div><br><br>
<!-- include后面跟的是组件名--><keep-alive include="HomeNews"><router-view></router-view></keep-alive></div>
</template><script>export default {name: "Home",/*mounted(){console.log("Home组件被挂载了")window.homeRoute=this.$routewindow.homeRouter=this.$router},beforeDestroy() {console.log("Home组件被销毁了")}*/}
</script><style scoped lang="less">
</style>
HomeNews.vue
<template>
<div><ul><li>新闻001 <input type="text"></li><li>新闻002 <input type="text"></li><li>新闻003 <input type="text"></li></ul>
</div>
</template><script>export default {name: "HomeNews",beforeDestroy() {console.log("HomeNews组件即将被销毁")}}
</script><style scoped></style>
HomeMessage.vue
<template><div><ul>
<!-- 跳转路由并携带params参数,to的字符串的写法--><li v-for="m in messageList" :key="m.id">
<!-- <router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{m.title}}</router-link>--><!-- 跳转路由并携带params参数,只能使用名字跳转,to的对象的写法--><router-link :to="{name:'xiangqing',query:{id:m.id,title:m.title}}">{{m.title}}</router-link><button @click="pushShow(m)">push查看</button><button @click="replaceShow(m)">replace查看</button><br></li></ul><hr><router-view></router-view></div>
</template><script>export default {name: "HomeMessage",data(){return{messageList:[{id:"001",title:"消息001"},{id:"002",title:"消息002"},{id:"003",title:"消息003"},]}},methods:{pushShow(m){console.log(this.$router)this.$router.push({name:'xiangqing',query:{id:m.id,title:m.title}})},replaceShow(m){this.$router.replace({name:'xiangqing',query:{id:m.id,title:m.title}})},},beforeDestroy() {console.log("HomeMessage组件即将被销毁")}}
</script><style scoped>
.active{color: black;
}
</style>
总结
- 作用:让不展示的路由组件保持挂载,不被销毁
- 具体编码:
<keep-alive include="HomeNews"><router-view></router-view>
</keep-alive>
两个新的生命周期钩子
保留缓存组件功能后新增的需求
HomeNews.vue
<template>
<div><div :style="{opacity}">欢迎学习Vue</div><ul><li>新闻001 <input type="text"></li><li>新闻002 <input type="text"></li><li>新闻003 <input type="text"></li></ul>
</div>
</template><script>export default {name: "HomeNews",data(){return{opacity: 1}},activated() {console.log("News组件被激活了")this.timer=setInterval(()=>{console.log("@")this.opacity-=0.01if(this.opacity<0) this.opacity=1},16)},deactivated() {console.log("News组件失活了")clearInterval(this.timer)}}
</script><style scoped></style>
HomeMessage.vue
<template><div><ul>
<!-- 跳转路由并携带params参数,to的字符串的写法--><li v-for="m in messageList" :key="m.id">
<!-- <router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{m.title}}</router-link>--><!-- 跳转路由并携带params参数,只能使用名字跳转,to的对象的写法--><router-link :to="{name:'xiangqing',query:{id:m.id,title:m.title}}">{{m.title}}</router-link><button @click="pushShow(m)">push查看</button><button @click="replaceShow(m)">replace查看</button><br></li></ul><hr><router-view></router-view></div>
</template><script>export default {name: "HomeMessage",data(){return{messageList:[{id:"001",title:"消息001"},{id:"002",title:"消息002"},{id:"003",title:"消息003"},]}},methods:{pushShow(m){console.log(this.$router)this.$router.push({name:'xiangqing',query:{id:m.id,title:m.title}})},replaceShow(m){this.$router.replace({name:'xiangqing',query:{id:m.id,title:m.title}})},},}
</script><style scoped>
.active{color: black;
}
</style>
Home.vue
<template><div><h1>我是Home的内容</h1><br><div class="btn-group" role="group" aria-label="..."><router-link type="button" class="btn btn-default" active-class="active" to="/home/news">News</router-link><router-link type="button" class="btn btn-default" active-class="active" to="/home/message">Message</router-link></div><br><br>
<!-- include后面跟的是组件名--><keep-alive include="HomeNews"><router-view></router-view></keep-alive></div>
</template><script>export default {name: "Home",/*mounted(){console.log("Home组件被挂载了")window.homeRoute=this.$routewindow.homeRouter=this.$router},beforeDestroy() {console.log("Home组件被销毁了")}*/}
</script><style scoped lang="less">
</style>
总结
- 作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态。
- 具体名字
(1)activated路由组件被激活时触发
(2)deactivated路由组件失活时触发
全局路由守卫
路由前置守卫
src/router/index.js
//该文件专门用于创建整个应用的路由器
import VueRouter from "vue-router";
//引入组件
import About from "@/pages/About";
import Home from "@/pages/Home";
import HomeNews from "@/pages/HomeNews";
import HomeMessage from "@/pages/HomeMessage";
import Detail from "@/pages/Detail";//创建并暴露一个路由器
const router=new VueRouter({routes:[{name:'guanyu',path:'/about',component:About},{name:"zhuye",path:'/home',component:Home,children:[{name:'xinwen',path:'news',component:HomeNews},{name:'xiaoxi',path:'message',component:HomeMessage,children:[{name:'xiangqing',// path:'detail/:id/:title', //nodejs的占位符,后面会填充内容path:'detail', //query的写法component:Detail,//props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件// props:{a:1,b:'你好啊'},//props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件// props:true,//props的第三种写法:函数式(最普通的写法)/*props($route){return {id:$route.query.id,title:$route.query.title}}*///第三种:函数式(解构赋值的写法)/*props({query}){return{id:query.id,title:query.title}}*///第三种:函数式(解构赋值之后再解构赋值)props({query:{id,title}}){return {id,title}}}]}]}]
})//全局前置路由守卫——初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to,from,next)=>{console.log("to",to)console.log("from",from)if(to.name=="xinwen"||to.path=="/home/message"){console.log(localStorage.getItem("school"))if(localStorage.getItem("school")==="lucky"){next()}else{alert("学校名字不对,无权限查看")}}else{next()}
})export default router
路由后置守卫及用户鉴权问题
src/router/index.js
//该文件专门用于创建整个应用的路由器
import VueRouter from "vue-router";
//引入组件
import About from "@/pages/About";
import Home from "@/pages/Home";
import HomeNews from "@/pages/HomeNews";
import HomeMessage from "@/pages/HomeMessage";
import Detail from "@/pages/Detail";//创建并暴露一个路由器
const router=new VueRouter({routes:[{name:'guanyu',path:'/about',component:About,meta:{title:"关于"}},{name:"zhuye",path:'/home',component:Home,meta:{title:"主页"},children:[{name:'xinwen',path:'news',component:HomeNews,meta:{isAuth:true,title:"新闻"}, //增加权限控制},{name:'xiaoxi',path:'message',component:HomeMessage,meta:{isAuth: true,title:"消息"},children:[{name:'xiangqing',// path:'detail/:id/:title', //nodejs的占位符,后面会填充内容path:'detail', //query的写法component:Detail,meta:{isAuth: true,title:"详情"},//props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件// props:{a:1,b:'你好啊'},//props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件// props:true,//props的第三种写法:函数式(最普通的写法)/*props($route){return {id:$route.query.id,title:$route.query.title}}*///第三种:函数式(解构赋值的写法)/*props({query}){return{id:query.id,title:query.title}}*///第三种:函数式(解构赋值之后再解构赋值)props({query:{id,title}}){return {id,title}}}]}]}]
})//全局前置路由守卫——初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to,from,next)=>{console.log("前置守卫",to,from)// if(to.name=="xinwen"||to.path=="/home/message"){if(to.meta.isAuth){ //判断是否需要鉴权if(localStorage.getItem("school")==="lucky"){next()}else{alert("学校名字不对,无权限查看")}}else{next()}
})//全局后置路由守卫——初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to,from)=>{console.log("后置路由守卫",to,from)document.title=to.meta.title||"xx系统"
})
export default router
总结
- 作用:对路由进行权限控制
- 分类:全局守卫、独享守卫、组件内守卫
- 全局守卫
//全局前置路由守卫——初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to,from,next)=>{console.log("前置守卫",to,from)if(to.meta.isAuth){ //判断是否需要鉴权(判断当前路由是否需要进行权限控制)if(localStorage.getItem("school")==="lucky"){//权限控制的具体规则next() //放行}else{alert("学校名字不对,无权限查看") //暂无权限}}else{next() //放行}
})//全局后置路由守卫——初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to,from)=>{console.log("后置路由守卫",to,from)if(to.meta.title){document.title=to.meta.title||"xx系统" //修改网页的title}else{document.title="vue_test" //修改网页的title}
})
export default router
独享路由守卫
src/router/index.js
//该文件专门用于创建整个应用的路由器
import VueRouter from "vue-router";
//引入组件
import About from "@/pages/About";
import Home from "@/pages/Home";
import HomeNews from "@/pages/HomeNews";
import HomeMessage from "@/pages/HomeMessage";
import Detail from "@/pages/Detail";//创建并暴露一个路由器
const router=new VueRouter({routes:[{name:'guanyu',path:'/about',component:About,meta:{title:"关于"}},{name:"zhuye",path:'/home',component:Home,meta:{title:"主页"},children:[{name:'xinwen',path:'news',component:HomeNews,meta:{isAuth:true,title:"新闻"}, //增加权限控制//独享前置路由守卫(只有前置)beforeEnter:(to, from, next)=>{if(to.meta.isAuth){ //判断是否需要鉴权if(localStorage.getItem('school')==='lucky'){next()}else{alert("学校名不对,无权限查看!")}}else{next()}}},{name:'xiaoxi',path:'message',component:HomeMessage,meta:{isAuth: true,title:"消息"},children:[{name:'xiangqing',// path:'detail/:id/:title', //nodejs的占位符,后面会填充内容path:'detail', //query的写法component:Detail,meta:{isAuth: true,title:"详情"},//props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件// props:{a:1,b:'你好啊'},//props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件// props:true,//props的第三种写法:函数式(最普通的写法)/*props($route){return {id:$route.query.id,title:$route.query.title}}*///第三种:函数式(解构赋值的写法)/*props({query}){return{id:query.id,title:query.title}}*///第三种:函数式(解构赋值之后再解构赋值)props({query:{id,title}}){return {id,title}}}]}]}]
})//全局后置路由守卫——初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to,from)=>{console.log("后置路由守卫",to,from)document.title=to.meta.title||"xx系统"
})
export default router
总结
- 独享守卫
//独享前置路由守卫(只有前置)beforeEnter(to, from, next){if(to.meta.isAuth){ //判断当前路由是否需要权限控制if(localStorage.getItem('school')==='lucky'){next()}else{alert("学校名不对,无权限查看!")}}else{next()}}
组件内路由守卫
src/router/index.js(改了about的用户鉴权)
//该文件专门用于创建整个应用的路由器
import VueRouter from "vue-router";
//引入组件
import About from "@/pages/About";
import Home from "@/pages/Home";
import HomeNews from "@/pages/HomeNews";
import HomeMessage from "@/pages/HomeMessage";
import Detail from "@/pages/Detail";//创建并暴露一个路由器
const router=new VueRouter({routes:[{name:'guanyu',path:'/about',component:About,meta:{isAuth:true,title:"关于"},//设置权限},{name:"zhuye",path:'/home',component:Home,meta:{title:"主页"},children:[{name:'xinwen',path:'news',component:HomeNews,meta:{isAuth:true,title:"新闻"}, //增加权限控制//独享前置路由守卫(只有前置)beforeEnter:(to, from, next)=>{if(to.meta.isAuth){ //判断是否需要鉴权if(localStorage.getItem('school')==='lucky'){next()}else{alert("学校名不对,无权限查看!")}}else{next()}}},{name:'xiaoxi',path:'message',component:HomeMessage,meta:{isAuth: true,title:"消息"},children:[{name:'xiangqing',// path:'detail/:id/:title', //nodejs的占位符,后面会填充内容path:'detail', //query的写法component:Detail,meta:{isAuth: true,title:"详情"},//props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件// props:{a:1,b:'你好啊'},//props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件// props:true,//props的第三种写法:函数式(最普通的写法)/*props($route){return {id:$route.query.id,title:$route.query.title}}*///第三种:函数式(解构赋值的写法)/*props({query}){return{id:query.id,title:query.title}}*///第三种:函数式(解构赋值之后再解构赋值)props({query:{id,title}}){return {id,title}}}]}]}]
})//全局前置路由守卫——初始化的时候被调用、每次路由切换之前被调用
/*router.beforeEach((to,from,next)=>{console.log("前置守卫",to,from)// if(to.name=="xinwen"||to.path=="/home/message"){if(to.meta.isAuth){ //判断是否需要鉴权if(localStorage.getItem("school")==="lucky"){next()}else{alert("学校名字不对,无权限查看")}}else{next()}
})*///全局后置路由守卫——初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to,from)=>{// console.log("后置路由守卫",to,from)document.title=to.meta.title||"xx系统"
})
export default router
About.vue
<template><h1>我是About的内容</h1>
</template><script>
export default {name: "About",/*mounted(){console.log("About组件被挂载了",this)window.aboutRoute=this.$routewindow.aboutRouter=this.$router},beforeDestroy() {console.log("About组件被销毁了")}*///通过路由规则,进入该组件时被调用beforeRouteEnter(to,from,next){console.log("About-beforeRouteEnter",to,from)if(to.meta.isAuth){if(localStorage.getItem("school")=="lucky"){next()}else{alert("学校名不对,无权限查看")}}else{next()}},//通过路由规则,离开该组件时被调用beforeRouteLeave(to,from,next){console.log("About--beforeRouteLeave",to,from)next()}
}
</script><style scoped></style>
总结
组件内守卫:
//进入守卫,通过路由规则,进入该组件时被调用
beforeRouteEnter(to,from,next){},
//离开守卫,通过路由规则,离开该组件时被调用
beforeRouteLeave(to,from,next){
}