路由原理
路由是Vue中的一个重要的插件。
Vue是单页面应用就一个HTML页面,但是我们要实现页面的跳转效果,那么我就需要使用路由。
单页面的跳转是什么呢?实际上就是局部改变,其实还是一个单页面,只是看起来像跳转的样子。
单页应用的路由模式有两种
1、哈希模式(利用hashchange 事件监听 url的hash 的改变)
2、history模式(使用此模式需要后台配合把接口都打到我们打包后的index.html上)
路由到底有什么作用?
下图淘宝例子:底部红色框中的按钮点击的话,绿色框中的内容会发生改变,实现单页面应用
路由安装和使用(vue2)
路由下载地址上个博客写过,没下的可以去看看。
导入路由插件:
<script src="../js/vue2.7.js"></script><!--vue文件--> <script src="../js/vue-router.js"></script><!--路由文件-->
安装路由插件到Vue中:
<script> //安装路由,前提要导入路由js Vue.use(VueRouter) </script>
创建VueRouter对象:
var Login = Vue.extends({ template:` <div> 我是登录页面 </div> ` }); // 创建VueRouter对象,并配置路由 var myRouter = new VueRouter({ // 配置路由 routes:[ // 指定路由链接、路由名称、路由页面(组件) {path:'/login',name:'login',component:Login} ] });
使用路由:
var app= new Vue({ el:'#app', // 引入到vue 实例中,并在模板中使用<router-view> router:myRouter, template:` <div> 头部 <router-view></router-view><!--路由出口--> 尾部 </div> ` })
路由跳转
路由的跳转有两种方式:
- 使用<router-link>标签
<router-link to='/login'></router-link>
- 编程式路由,使用js
this.$router.push({path:'/login'}); this.$router.replace({path:'/login'});
说明:
- this.$router.push(); 会向history中添加记录
- this.$router.replace();不会向history中添加记录。
- this.$router.go(-1)常用来做返回上一个地址。
push和replace的区别就是在跳转后,后退或前进能不能使用
路由中的对象:
- this.$route 路由信息对象,只读。
- this.$router 路由操作对象,只写。
跳转实例:
<!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="/login">登录</router-link><!--登录的标签方式--> <router-link to="/person">个人</router-link><!--个人的标签方式--> <button @click="toLogin">登录按钮</button><!--登录的点击事件方式--> <button @click="toPerson">个人按钮</button><!--个人的点击事件方式--> <!--下面是路由出口--> <router-view></router-view> 尾部 </div> </body> <script src="../js/vue2.7.js"></script> <script src="../js/vue-router.js"></script> <script> //安装路由,前提要导入路由js Vue.use(VueRouter) //创建一个登录子组件 var login={ template:` <div> 登陆页面 </div> `, } //创建一个个人子组件 var person={ template:` <div> 个人页面 </div> `, } //创建路由配置实例,主要实现 路由和子组件之间的映射 var myrouter=new VueRouter({ routes: [ {path:'/login',name:'login',component:login}, {path:'/person',name:'person',component:person} ] }) let app=new Vue({ el:"#app", router:myrouter, methods: { toLogin(){ this.$router.push({ path:'/login' }) }, toPerson(){ this.$router.replace({ path:'/person' }) }, }, }) </script> </html>
路由的传值和取值
查询参
配置。查询参可以和path属性匹配,也可以和name属性匹配。
<router-link :to="{path:'/login',query:{id:queryid}}"></router-link>
或者
<router-link :to="{name:'login',query:{id:queryid}}"></router-link>
或者
this.$router.push({path:'/login',query:{id:this.queryid}});
取参
// 此代码可以写到子组件的钩子函数中 this.$route.query.id
路由参
配置路由规则
var router = new VueRouter({ routers:[ // 需要在配置路由规则时,使用冒号指定参数 {name:'login',path:'/login/:id',component:LoginVue} ] });
配置。意:在这里path和params两个参数不能同时使用,
路由参配置的时候要使用name,因为path会根据参数的不同会改变。
<router-link :to="{name:'login',params:{id:paramId}}"></router-link>
或者
this.$router.push({name:'login',params:{id:this.paramId}});
取参
// 此代码可以写到子组件的钩子函数中 this.$route.params.id
传值实例:
<!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="{path:'/login',query:{id:loginId}}">登录query-link方式</router-link> <button @click="toLogin">登录query-按钮方式</button> <router-link :to="{name:'person',params:{id:personId}}">个人params-link方式</router-link> <button @click="toPerson">个人params-按钮方式</button> <br> <router-view></router-view><!--路由出口--> 尾部 </div> </body> <script src="../js/vue2.7.js"></script> <script src="../js/vue-router.js"></script> <script> //安装路由,前提要导入路由js Vue.use(VueRouter) var login={ template:` <div> 登陆页面 </div> `, mounted() { console.log(this.$route.query.id); }, } //创建一个个人子组件 var person={ template:` <div> 个人页面 </div> `, mounted() { console.log(this.$route.params.id); }, } //创建路由配置实例,主要实现 路由和子组件之间的映射 var myrouter=new VueRouter({ routes: [ {path:'/login',name:'login',component:login}, {path:'/person/:id',name:'person',component:person} ] }) let app=new Vue({ el:"#app", router:myrouter, data() { return { loginId:66, personId:33 } }, methods: { toLogin(){ this.$router.push({ path:'/login', query:{id:this.loginId} }) }, toPerson(){ this.$router.push({ name:'person', params:{id:this.personId} }) }, }, }) </script> </html>
查询参和路由参的区别:
在地址栏参数的不同
查询参: 路由参:
大家会出现的问题:
相同路由,但参数不同。造成页面不刷新的问题,只需要给路由出口加一个属性就行。
<router-view :key="$route.fullPath"></router-view>
嵌套路由
路由间有层级关系。他们在模板中也有嵌套关系。
可以一次性配置多个路由。
嵌套实例:
实例里面写的都有注释方便大家理解,对于不理解的地方大家多看几遍,或许就能理解了。
<!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-view></router-view><!--路由出口--> </div> </body> <script src="../js/vue2.7.js"></script> <script src="../js/vue-router.js"></script> <script> Vue.use(VueRouter); //导航组件 let nav={ template:` <div> <router-link :to="{name:'nav.index'}">首页</router-link> <router-link :to="{name:'nav.person'}">个人</router-link> <router-link :to="{name:'nav.message'}">消息</router-link> <router-view></router-view><!--导航组件的路由出口--> </div> ` } //主页面子组件 let index={ template:` <div>主页面</div> ` } //个人页面子组件 let person={ template:` <div>个人页面</div> ` } //消息页面子组件 let message={ template:` <div>消息页面</div> ` } let router=new VueRouter({ routes:[ { path:'/nav', name:'nav', component:nav, children:[//配置二级路由 {path:'',redirect:'/nav/index'},//默认显示二级路由页面链接是/nav/index的路由 {path:'index',name:'nav.index',component:index}, {path:'person',name:'nav.person',component:person}, {path:'message',name:'nav.message',component:message}, ] }, { path:'', redirect:'/nav'//默认显示页面链接是/nav的路由 } ] }) let app = new Vue({ el:'#app', router,//这个地方使用的是简写根据ES6新语法,对象名和参数相同可以直接使用对象名。 }); </script> </html>
路由守卫
可以做登录的验证判断,购物车是否购买后跳转页面判断。
使用路由的钩子函数beforeEach实现
守卫实例:
我将路由守卫放在了刚才的嵌套路由的实例里面,作用是判断路径是否是首页
<!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-view></router-view><!--路由出口--> </div> </body> <script src="../js/vue2.7.js"></script> <script src="../js/vue-router.js"></script> <script> Vue.use(VueRouter); //导航子组件 let nav={ template:` <div> <router-link :to="{name:'nav.index'}">首页</router-link> <router-link :to="{name:'nav.person'}">个人</router-link> <router-link :to="{name:'nav.message'}">消息</router-link> <router-view></router-view><!--导航组件中的路由出口--> </div> ` } //主页面子组件 let index={ template:` <div>主页面</div> ` } //个人页面子组件 let person={ template:` <div>个人页面</div> ` } //消息页面子组件 let message={ template:` <div>消息页面</div> ` } let router=new VueRouter({ routes:[ { path:'/nav', name:'nav', component:nav, children:[//配置二级路由 {path:'',redirect:'/nav/index'},//默认显示二级路由页面链接是/nav/index的路由 {path:'index',name:'nav.index',component:index}, {path:'person',name:'nav.person',component:person}, {path:'message',name:'nav.message',component:message}, ] }, { path:'', redirect:'/nav'//默认显示页面链接是/nav的路由 } ] }) let app = new Vue({ el:'#app', router,//这个地方使用的是简写根据ES6新语法,对象名和参数相同可以直接使用对象名。 mounted() { this.$router.beforeEach((to,from,next)=>{ console.log(to); if(to.path=='/nav/index'){ // 跳转到目标路由 next(); }else{ //如果路径不对的话延时两秒再进入 setTimeout(function(){ next(); },2000); } }); } }); </script> </html>