一、前言#
在上一章的学习中,我们简单介绍了前端路由的概念,以及如何在 Vue 中通过使用 Vue Router 来实现我们的前端路由。但是在实际使用中,我们经常会遇到路由传参、或者一个页面是由多个组件组成的情况。本章,我们就来介绍下在这两种情况下 Vue Router 的使用方法以及一些可能涉及到的概念。
学习系列目录地址:https://www.cnblogs.com/danvic712/p/9549100.html
仓储地址:https://github.com/Lanesra712/VueTrial/tree/master/chapter02-bronze/router/pass
二、干货合集#
1、命名路由#
在某些时候,我们期望生成的路由 URL 地址可能会很长,在使用中可能会显得有些不便。这时候通过一个名称来标识一个路会更方便一些,因此在 Vue Router 中,我们可以在创建 Router 实例的时候,通过在 routes 配置中给某个路由设置名称,从而方便的调用路由。
const router = new VueRouter({ routes: [ { path: '/form', name: 'form', component: '<div>form 组件</div>' } ] })
当我们使用命名路由之后,当需要使用 router-link 标签进行跳转时,就可以采取给 router-link 的 to 属性传一个对象的方式,跳转到指定的路由地址上。
<router-link :to="{ name: 'form'}">User</router-link>
2、命名视图#
当我们打开一个页面时,整个页面可能是由多个 Vue 组件所构成的,例如,我们的后台管理首页可能是由 sidebar (侧导航) 、header(顶部导航)和 main (主内容)这三个 Vue 组件构成的。此时,当我们通过 Vue Router 构建路由信息时,如果一个 URL 只能对应一个 Vue 组件,整个页面肯定是无法正确显示的。
在上一章的学习中,我们在构建路由信息的时候有使用到两个特殊的标签:router-view 和 router-link。通过 router-view 标签,我们就可以指定组件渲染显示到什么位置。因此,当我们需要在一个页面上显示多个组件的时候,就需要在页面中添加多个的 router-view 标签。
那么,是不是可以通过一个路由对应多个组件,然后按需渲染在不同的 router-view 标签上呢?按照上一章中介绍的关于 Vue Router 的使用方法,我们可以很容易的实现下面的代码。
<div id="app"> <router-view></router-view> <div class="container"> <router-view></router-view> <router-view></router-view> </div> </div> <template id="sidebar"> <div class="sidebar"> sidebar </div> </template> <script> // 1、定义路由跳转的组件模板 const header = { template: '<div class="header"> header </div>' } const sidebar = { template: '#sidebar', } const main = { template: '<div class="main"> main </div>' } // 2、定义路由信息 const routes = [{ path: '/', component: header }, { path: '/', component: sidebar }, { path: '/', component: main }] const router = new VueRouter({ routes }) // 3、挂载到当前 Vue 实例上 const vm = new Vue({ el: '#app', data: {}, methods: {}, router: router }); </script>
可以看到,并没有实现我们想要实现的效果,当我们将一个路由信息对应到多个组件时,不管有多少个的 router-view 标签,程序都会将第一个组件渲染到所有的 router-view 标签上。
因此,在这种情况下,我们需要实现的是一个路由信息可以按照我们的需要去渲染到页面中指定的 router-view 标签上,而在 Vue Router 中,我们则可以通过命名视图的方式实现我们的需求。
命名视图,从名称上看可能无法阐述的很清楚,与命名路由的实现方式相似,命名视图通过在 router-view 标签上设定 name 属性,之后,在构建路由与组件的对应关系时,以一种 name:component 的形式构造出一个组件对象,从而指明是在哪个 router-view 标签上加载什么组件。
注意,这里在指定路由对应的组件时,使用的是 components(包含 s)属性进行配置组件。实现命名视图的代码如下所示。
<div id="app"> <router-view></router-view> <div class="container"> <router-view name="sidebar"></router-view> <router-view name="main"></router-view> </div> </div> <script> // 2、定义路由信息 const routes = [{ path: '/', components: { default: header, sidebar: sidebar, main: main } }] </script>
在 router-view 中,默认的 name 属性值为 default,所以这里的 header 组件对应的 router-view 标签就可以不设定 name 属性值。完整的示例代码如下。
<div id="app"> <router-view></router-view> <div class="container"> <router-view name="sidebar"></router-view> <router-view name="main"></router-view> </div> </div> <template id="sidebar"> <div class="sidebar"> sidebar </div> </template> <script> // 1、定义路由跳转的组件模板 const header = { template: '<div class="header"> header </div>' } const sidebar = { template: '#sidebar' } const main = { template: '<div class="main"> main </div>' } // 2、定义路由信息 const routes = [{ path: '/', components: { default: header, sidebar: sidebar, main: main } }] const router = new VueRouter({ routes }) // 3、挂载到当前 Vue 实例上 const vm = new Vue({ el: '#app', data: {}, methods: {}, router: router }); </script>
3、路由传参#
在很多的情况下,例如表单提交,组件跳转之类的操作,我们需要使用到上一个表单、组件的一些数据,这时我们就需要将需要的参数通过参数传参的方式在路由间进行传递。
例如,在下面的示例中,我们想要实现通过点击 main 组件中的子组件 form 组件上的按钮,将表单的内容传递到 info 子组件中进行显示,功能示意图如下所示。
3.1、query 传参
query 查询参数传参,就是将我们需要的参数以 key=value 的方式放在 url 地址中。例如这里的需求,我们需要在 info 组件中显示上一个页面的数据,所以我们的 info 页面显示的 URL 地址应该为 /info?email=xxx&password=xxx,这里的 email 和 password 参数值则是 form 组件上用户输入的值。之后,我们通过获取这两个参数值即可实现我们的需求。
当我们将实例化的 VueRouter 对象挂载到 Vue 实例后,Vue Router 在我们的 Vue 实例上创建了两个属性对象 this.$router(router 实例) 和 this.$route(当前页面的路由信息)。从下图可以看到,我们可以通过 vm.$route 获取到当前页面的路由信息,而这里的 query 对象则是我们需要的。
可以看到,这时我们就可以直接通过 $route.query.参数名 的方式获取到对应的参数值。同时可以发现,fullPath 属性可以获取到当前页面的地址和 query 查询参数,而 path 属性则只是获取到当前的路由信息。
同时,因为在使用 Vue Router 时已经将 VueRouter 实例挂载到 Vue 实例上,因此就可以直接通过调用 $router.push 方法来导航到另一个页面,所以这里 form 组件中的按钮事件,我们就可以使用这种方式完成路由地址的跳转,完整的代码如下。
<div id="app"> <div class="row"> <div class="col"> <router-view></router-view> </div> </div> <div class="row"> <div class="col-sm-2 sidebar"> <router-view name="sidebar"></router-view> </div> <div class="col-sm-10 main"> <router-view name="main"></router-view> </div> </div> </div> <template id="sidebar"