vue-router详尽:编程式导航、路由重定向、动态路由匹配、路由别名、嵌套路由、命名视图 缺乏、安全感 2021-09-17 05:32 659阅读 0赞 ### vue-router编程式导航 ### 在vue项目中经常用到this.$router.push() 和 this.$router.replace() 方法进行路由跳转就是编程式导航。。。 **通俗理解编程式导航:通过操作$router实例的JavaScript代码实现路由跳转。点击 `<router-link :to="...">` 等同于调用 `router.push(...)`。$router实例的方法有push()、replace()、go()方法,也可以进行路由传参。** 先上代码简单入手看效果: demo基于vue-cli创建的,项目结构如图: ![20181210104946661.png][] 第一步:定义路由文件 router >index.js如下 import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' import home from '@/components/Home' //引入组件 Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'HelloWorld', component: HelloWorld }, { path: '/home', //可以定义路由路径、命名、组件、参数、别名、重定向 name: 'home', component: home }, ] }) 第二步:helloWorld页面使用声明式和编程式导航到home组件的按钮,helloWorld组件如下 <template> <div class="hello"> <h1>{ { msg }} 页面</h1> <router-link to="/home">声明式使用router-link路由导航到home页面</router-link><br> <button @click="pushToHome()">js编程式push方法导航到home页面</button> <button @click="replaceToHome()">js编程式replace方法导航到home页面</button><br> <button @click="goNext()">js编程式go方法导航到history记录的下一个页面</button> <router-view></router-view> </div> </template> <script> export default { name: 'HelloWorld', data () { return { msg: 'Welcome to HelloWorld' } }, methods:{ pushToHome:function(){ this.$router.push("/home",function(){ //push()方法的使用,包括导航成功或失败的回调函数 console.log("导航成功的回调函数"); },function(){ console.log("导航中止的回调函数"); }); }, replaceToHome:function(){ //replace()方法的使用 this.$router.replace("/home"); }, goNext:function(){ //go()方法的使用 this.$router.go(1); } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> button { margin:10px; } </style> 第三步骤页面:home组件中可以使用router.go(-1) 返回到上一个历史记录中的页面;无记录时点击无效。home组件如下 <template> <div class="hello"> <h1>{ { msg }}</h1> <button @click="goBack()">js编程式go方法返回history页面</button> </div> </template> <script> export default { name: 'Home', data () { return { msg: 'Welcome to Home 主页!!!!' } }, methods:{ goBack:function(){ this.$router.go(-1); } } } </script> <style scoped> h1, h2 { color:red; } </style> ### **router.push(**location, onComplete, onAbort**)方法** ### 1、router.push() 方法,参数分别指的是导航到 **新的url、导肮完成的回调函数、导航中止的回调函数 **; 2、router.push() 方法 **会向history栈添加一个新的记录 **,所以当用户点击浏览器后退按钮时,则回到之前的 URL。 3、router.push(location)方法使用 //使用路由的path值 this.$router.push("/router1"); //使用包含路由path键值的对象 this.$router.push({path:'/router1'}); //使用包含路由name键值的对象 this.$router.push({name:'routerNum1'}); //使用包含name键值和params参数对象的对象, //注意:该方式params传参浏览器页面不在url中显示参数,但是会页面刷新的时候丢失参数 this.$router.push({name:'routerNum1',params:{userId:123}}); //path键值结合params的形式传参无效 this.$router.push({path:'/router1',params:{userId:123}}); //可以使用path键值结合query的形式传参 this.$router.push({path:'/router1',query:{userId:123}}); //使用path值拼接参数来传参,注意这里使用的不是单引号!!! const userId=123; this.$router.push({path:`/router1/${userId}`}); 4、 push()编程式导航注意点: const userId = 123 1、router.push({ path: `/router1/${userId}` }) // 注意使用反引号 2、router.push({ path: '/router1', params: { userId }}) // 注意path键值结合params传参无效 3、router.push({ name: '/routerNum1', params: { userId }}) // 注意该方式在浏览器url不显示参数,但是页面刷新会导致参数丢失 4、小demo使用验证如下: 第一步:定义路由文件 router >index.js如下 import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' import home from '@/components/Home' import router1 from '@/components/Router1' import router2 from '@/components/Router2' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'HelloWorld', component: HelloWorld }, { path: '/home', name: 'home', component: home }, { path: '/router1', name: 'routerNum1', component: router1 }, { path: '/router2', name: 'routerNum2', component: router2 }, ] }) 第二步:home.vue组件文件代码如下。 <template> <div class="hello"> <h3>{ { msg }}</h3> <button @click="goBack()">js编程式go方法返回history页面</button> <hr> <h3>js编程式导航中push方法的使用:</h3> <button @click="pathTo()">push方法的url参数使用path值导航</button> <button @click="pathObjectTo()">push方法的url参数使用path对象导航</button><br> <button @click="nameObjectTo()">push方法,包含路由命名name键值的对象导航</button><br> <button @click="nameParamTo()">push方法,包含路由命名name键值的对象结合params传参</button><br> <button @click="pathParamTo()">push方法,path键值对象导航结合params传参,参数传递失败</button> <button @click="pathQueryTo()">push方法,path键值对象导航结合query传参</button><br> <button @click="pathandTo()">push方法,path值拼接参数来传参</button> </div> </template> <script> export default { name: 'Home', data () { return { msg: 'Welcome to Home 主页!!!!' } }, methods:{ goBack:function(){ this.$router.go(-1); }, pathTo:function(){ //使用路由的path值 this.$router.push("/router1"); }, pathObjectTo:function(){ //使用包含路由path键值的对象 this.$router.push({path:'/router1'}); }, nameObjectTo:function(){ //使用包含路由name键值的对象 this.$router.push({name:'routerNum1'}); }, nameParamTo:function(){ //使用包含name键值和params参数对象的对象 this.$router.push({name:'routerNum1',params:{userId:123}}); }, pathParamTo:function(){ //path键值结合params的形式传参无效 this.$router.push({path:'/router1',params:{userId:123}}); }, pathQueryTo:function(){ //可以使用path键值结合query的形式传参 this.$router.push({path:'/router1',query:{userId:123}}); }, pathandTo:function(){ const userId=123; this.$router.push({path:`/router1/${userId}`}); } } } </script> <style scoped> h1, h2 { color:red; } </style> 第三步:router1.vue组件代码如下,使用**this.$route.params.paramName或query.queryName接收路由传的参数**。 <template> <div class="hello"> <h3>{ { msg }}</h3> <button @click="goBack()">js编程式go方法上一个路由页面</button> <p>{ {fromRouterParams}}</p> <p>{ {fromRouterQuery}}</p> </div> </template> <script> export default { name: 'Router1', data () { return { msg: 'Welcome to Router1' , fromRouterParams:this.$route.params.userId, fromRouterQuery:this.$route.query.userId, } }, methods:{ goBack:function(){ this.$router.go(-1); }, } } </script> <style scoped> h1, h2 { color:red; } </style> ### **router.replace(**location, onComplete, onAbort**)方法** ### 跟 `router.push` 很像,唯一的**不同就是,它不会向 history 添加新记录**,而是跟它的方法名一样 —— **替换掉当前的 history 记录;** # # ### **router.go(**n**)方法** ### 1、参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 `window.history.go(n)`。 [Browser History APIs][]点击了解更多 2、使用: // 在浏览器记录中前进一步,等同于 history.forward() router.go(1) // 后退一步记录,等同于 history.back() router.go(-1) // 前进 3 步记录 router.go(3) // 如果 history 记录不够用,那就默默地失败呗 router.go(-100) router.go(100) Vue Router 的导航方法 (`push`、 `replace`、 `go`) 在各类路由模式 (`history`、 `hash` 和 `abstract`) 下表现一致。 ## ## ### **路由重定向:** ### 路由配置\{ path: '/a', redirect: '/b' \},路由重定向是指当用户访问 `/a`时,**路由跳转到b路由,URL 将会被替换成 `/b`** 1、在路由配置文件 router >index.js上使用: const router = new VueRouter({ routes: [ { path: '/router1', redirect: '/router2' }, //是从 /route1 重定向到 /router2 { path: '/b', redirect: {name:'foo'} }, //重定向的目标也可以是一个命名的路由 { path: '/c', redirect:(to)=>{ // 方法接收 目标路由 作为参数 // return 重定向的 字符串路径/路径对象 //注意:导航守卫应用在导航跳转目标to上 }}, ] }) 2、注意在给**路由设置有路由重定向时,再使用的路由导航会应用在跳转to指向的路由上**,如下路由router1上的导航守卫无效 { path: '/router1', redirect: '/router2', name: 'routerNum1', component: router1, beforeEnter:(from,to,next)=>{ //导航守卫无效 console.log("在路由1上进行重定向"); next(); } }, { path: '/router2', name: 'routerNum2', component: router2, beforeEnter:(from,to,next)=>{ console.log("进入到了路由2"); next(); } }, 3、**重定向指向自身会报错**:\[Vue warn\]: Error in beforeCreate hook: "RangeError: Maximum call stack size exceeded,使用动态路径参数传参除外 ### **路由别名** ### 路由别名**可以理解为路由的 '小名'**,可以使用路由别名进行路由导航 路由 /router2 的别名 alias 为 /secondRouter ,那么**使用别名访问 /secondRouter 时,url是/secondRouter,**导航跳转到路由 /router2 ,如下 {path: '/router2', name: 'routerNum2', alias:'/secondRouter',component: router2 }, ### 动态路由匹配: ### 使用情况: 1、如果导航目的地和当前路由相同,只有参数发生了改变 (比如从一个用户资料到另一个 `/users/1` -> `/users/2`),需要**组件复用,组件复用意味着组件的生命周期钩子函数不会被调用**! 2、或者所有路由映射到同一个组件模式渲染,只是参数不同时。那么,我们可以在 `vue-router` 的路由路径中**使用“动态路径参数”(dynamic segment)** 来达到这个效果: **动态路径参数的使用** 第一步:动态路径参数的使用需要在路由配置文件上使用冒号开头的形式 { //动态路径参数的使用 冒号开头 //那么像/router1/1 和/router1/2都将跳转到该路由页面 path: '/router1/:userNum', name: 'routerNum1', component: router1, }, 第二步:使用this.$router.push(\{ **path: \`/router1/$\{userNum1\}\`** \}); 形式进行动态路径传参,**注意反引号,url中的参数不会刷新丢失** <template> <div class="hello"> <h3>{ { msg }}</h3> <button @click="goBack()">js编程式go方法返回history页面</button> <hr> <h3>js动态路由匹配的使用:</h3> <button @click="pathParam1To()">动态路径参数1导航</button> <button @click="pathParam2To()">动态路径参数2导航</button> <hr> <button @click="diffParamsTo()">导航到当前组件(组件复用),但传递的参数不同</button> </div> </template> <script> export default { name: 'Home', data () { return { msg: 'Welcome to Home 主页!!!!' } }, watch: { '$route' (to, from) { // 对路由变化作出响应... console.log('路由发生变化'); console.log(this.$route.params.userNum); } }, methods:{ goBack:function(){ this.$router.go(-1); }, pathParam1To:function(){ let userNum1=111111; this.$router.push({path:`/router1/${userNum1}`}); }, pathParam2To:function(){ let userNum2=222222; this.$router.push({path:`/router1/${userNum2}`}); }, diffParamsTo:function(){ let userNum2=666; this.$router.push({path:`/router1/${userNum2}`}); }, } } </script> <style scoped> h1, h2 { color:red; } </style> 第三步:可以在路由组件中使用this.$route.params获取动态路径参数,如下 <p>{ {this.$route.params.userNum}}</p> **组件复用** 复用组件时,想对路由参数的变化作出响应的话,你可以简单地 watch (监测变化) `$route` 对象: watch: { '$route' (to, from) { // 对路由变化作出响应... console.log('路由发生变化'); console.log(this.$route.params.userNum); } }, 也可以使用2.2中引入的 beforeRouteUpdate导航守卫来响应这个变化 (比如抓取用户信息)。[组件内导航守卫][Link 1]可以点击了解 const User = { template: '...', beforeRouteUpdate (to, from, next) { // react to route changes... // don't forget to call next() } } ### 嵌套路由 ### 嵌套路由指的是在渲染的路由组件页面中包含了下级路由渲染出口(<router-view>),浏览器的URL 中各段动态路径也按某种结构对应嵌套的各层组件, 在项目的app.vue 文件中<router-view>是最顶层的出口,渲染最高级路由匹配到的组件。 <div id="app"> <router-view></router-view> </div> 第一步:定义路由配置文件router >index.js,**在路由上使用children属性定义下级路由** import Vue from 'vue' import Router from 'vue-router' import helloWorld from '@/components/HelloWorld' import home from '@/components/Home' import book from '@/components/Book' import water from '@/components/Water' Vue.use(Router) export default new Router({ routes: [ { path: '/', component:helloWorld }, { path: '/home', component: home, children:[ { path:'', //当访问的子路由路径无匹配时会指向到该空的子路由 component:water, }, { path:'book', component:book, }, { path:'water', component:water, }, ] }, ] }) 第二步:路由组件home.vue的内容,子路由导航包括了声明式和编程式导航 <template> <div class="hello"> <h3>{ {msg}}</h3> <button @click="showBookRouter()">点击按钮显示子路由页面book</button> <button @click="showWaterRouter()">点击按钮显示子路由页面water</button><br> <router-link to="/home/book">book</router-link> <router-link to="/home/water">water</router-link> <router-link to="/home/">foo</router-link> <router-view></router-view> </div> </template> <script> export default { name: 'Home', data () { return { msg: 'Welcome to Home !!!' } }, methods:{ showBookRouter:function(){ this.$router.push('/home/book'); //编程式路由导航 }, showWaterRouter:function(){ this.$router.push('/home/water'); }, } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h3 { color:red; } </style> 第三步:子组件book.vue 和water.book这里就不写了 ### **命名视图** ### 同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 `sidebar` (侧导航) 和 `main` (主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 `router-view` 没有设置名字,那么默认为 `default`。 <router-view class="view one"></router-view> <router-view class="view two" name="a"></router-view> <router-view class="view three" name="b"></router-view> 一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 `components`配置 (带上 s): { path: '/', components: { default: water, a: book, b: water } } 参考网址:官网API [https://router.vuejs.org/zh/guide/essentials/navigation.html][https_router.vuejs.org_zh_guide_essentials_navigation.html] [20181210104946661.png]: /images/20210726/d92367d962bd4a57a147244d19aa3789.png [Browser History APIs]: https://developer.mozilla.org/en-US/docs/Web/API/History_API [Link 1]: https://mp.csdn.net/postedit/84839419 [https_router.vuejs.org_zh_guide_essentials_navigation.html]: https://router.vuejs.org/zh/guide/essentials/navigation.html
还没有评论,来说两句吧...