Vue(基础六)_嵌套路由(续)
一、前言
1、路由嵌套里面的公共路由
2、keep-alive路由缓存
3、导航守卫
二、主要内容
1、路由嵌套里面的公共路由:
(1)如下图所示是掘金网的首页,上面是父组件,里面是子组件,在切换里面的导航的时候发现里面的结构并没有变化,只是数据发生了变化,为了避免切换的时候反复操作DOM,这时候将里面的内容部分形成一个公共的组件,这个时候哦需要用watch来监听路由的变化,然后根据不同的路由来做出响应
(2)实现路由复用的代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id='app'> </div> <script type="text/javascript" src="node_modules/vue/dist/vue.js"></script> <script type="text/javascript" src="node_modules/vue-router/dist/vue-router.js"></script> <script type="text/javascript"> var Timeline = { template:`<div id='timeline'> <router-link :to ="{name:'comDesc',params:{id:'frontend'}}">前端</router-link> <router-link :to ="{name:'comDesc',params:{id:'backend'}}">后端</router-link> <router-view></router-view> </div>` } var Pins={ template:'<div>我是沸点</div>' } //这是子组件里面公共的部分,当点击前端时,创建出了这个公共组件,当点击后端时没有创建 var ComDesc = { data(){ return { msg:'' } }, template:'<div>我是{{msg}}</div>', created(){ console.log(1) }, watch:{//这里检查到了路由是从前端到后端 '$route'(to, from){ console.log(to); console.log(from) this.msg = to.params.id } } } var router = new VueRouter({ routes:[ { path:'/timeline', component:Timeline, children:[ { name:'comDesc', path:'/tiemline/:id', component:ComDesc } ] }, { path:'/pins', component:Pins } ] }) var App = { template:` <div> <router-link to='/timeline'>首页</router-link> <router-link to='/pins'>沸点</router-link> <router-view></router-view> </div> ` } new Vue({ el:'#app', router:router,//6.交给这个实例化对象去管理 template:`<App />`, components:{ App } }) </script> </body> </html>
(3)如果想要根据你上面的路由变化,让不同的路由做出响应,这时候要用watch()来监听,当监听到to, form发生变化的时候,就可以根据不同的路径,发送响应,拿到不同的数据
2、keep-alive组件缓存的使用
用法:当我们反复切换某两个DOM对象的时候,就一直在创建销毁创建销毁,这样对页面中dom的消耗是很大的,为了避免这种情况,用keep-alive来让组件激活与失活。
下面演示案例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id='app'> </div> <script type="text/javascript" src="node_modules/vue/dist/vue.js"></script> <script type="text/javascript" src="node_modules/vue-router/dist/vue-router.js"></script> <script type="text/javascript"> var Timeline = {//反复点击,说明这个组件一直在创建销毁创建销毁,这样对页面的消耗会很大 template:`<div id='timeline'> 我是首页 </div>`, created(){ console.log('首页组件创建了') }, mounted(){ console.log('首页组件DOM加载了') }, destroyed(){ console.log('首页组件销毁了') } } var Pins={ //点过去,点回来,组件会重新创建,肯定会变回原来的状态 template:`<div><h3 @click='clickHandler'>我是沸点</h3></div>`, methods:{ clickHandler(e){ e.target.style.color = 'red' } }, created(){ console.log('沸点组件创建了') }, mounted(){ console.log('沸点组件DOM加载了') }, destroyed(){ console.log('沸点组件销毁了') } } //这是子组件里面公共的部分,当点击前端时,创建出了这个公共组件,当点击后端时没有创建 var router = new VueRouter({ routes:[ { path:'/timeline', component:Timeline, }, { path:'/pins', component:Pins } ] }) var App = { template:` <div> <router-link to='/timeline'>首页</router-link> <router-link to='/pins'>沸点</router-link> <keep-alive> <router-view></router-view> </keep-alive> </div> ` } new Vue({ el:'#app', router:router,//6.交给这个实例化对象去管理 template:`<App />`, components:{ App } }) </script> </body> </html>
演示结果说明:
3、导航守卫
用法:有些网页在访问某些地方的时候需要用到权限, 比如当用户访问首页的时候可以访问首页里面的内容,当访问其他的时候,会判断用户是否已经登录了,如果没有登录,显示登录组件,已经登录则可以直接访问
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id='app'> <router-link to='/home'>首页</router-link> <router-link to='/blog'>我的博客</router-link> <router-link to = '/login'>登录</router-link> <router-view></router-view> </div> <script type="text/javascript" src="node_modules/vue/dist/vue.js"></script> <script type="text/javascript" src="node_modules/vue-router/dist/vue-router.js"></script> <script type="text/javascript"> Vue.use(VueRouter); var Home = { template:` <div> 我是首页 </div> ` }; var Blog = { template:` <div> 我是博客 </div> ` }; var Login = { data(){ return { name:'', pwd:'' } }, template:` <div> <input type="text" v-model ='name'/> <input type="text" v-mode = 'pwd'/> <input type="button" value ='登录' @click = 'login'/> </div> `, methods:{ login(){ localStorage.setItem('user', {name:this.name,pwd:this.pwd}); // 编程式导航 this.$router.push({name:'blog'}); } } }; var router = new VueRouter({ routes:[ { path:'/', redirect:'/home' }, { path:'/home', component:Home }, { name:'blog', path:'/blog', component:Blog, // 给未来路由 做权限控制 全局路由守卫 来做参照条件 meta:{ // 表明用户访问该组件是需要登录 auth:true } }, { path:'/login', component:Login } ] }); router.beforeEach((to, from, next) => { console.log(to); console.log(from); if (to.meta.auth) { //用户点击了博客链接 该用户未登录 需要登录判断 准备跳转登录页面 if(localStorage.getItem('user')){ // alert(1); // 不为空 放行 next(); }else{ // alert(2); // 用户需要登录 next({ path:'/login' }); } }else{ // 直接放行 next();//如果不调用next 就会卡住 } }); new Vue({ el:'#app', router, methods:{ clear(){ localStorage.removeItem('user'); this.$router.push('/login'); } } }); </script> </body> </html>
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中。
每个守卫方法接收三个参数:
to: Route: 即将要进入的目标 路由对象
from: Route: 当前导航正要离开的路由
next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
next(false): 中断当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。
next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
确保要调用 next 方法,否则钩子就不会被 resolved。
三、总结