[Vue 牛刀小试]:第十三章 - Vue Router 基础使用再探(命名路由、命名视图、路由传参)
一、前言
在上一章的学习中,我们简单介绍了前端路由的概念,以及如何在 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">
<div>
<ul>
<router-link v-for="(item,index) in menu" :key="index" :to="item.url" tag="li">{{item.name}}
</router-link>
</ul>
</div>
</template> <template id="main">
<div>
<router-view> </router-view>
</div>
</template> <template id="form">
<div>
<form>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp"
placeholder="Enter email" v-model="email">
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone
else.</small>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password"
v-model="password">
</div>
<button type="submit" class="btn btn-primary" @click="submit">Submit</button>
</form>
</div>
</template> <template id="info">
<div class="card" style="margin-top: 5px;">
<div class="card-header">
输入的信息
</div>
<div class="card-body">
<blockquote class="blockquote mb-0">
<p>Email Address:{{ $route.query.email }} </p>
<p>Password:{{ $route.query.password }}</p>
<footer class="blockquote-footer">Someone famous in <cite title="Source Title">Source Title</cite>
</footer>
</blockquote>
</div>
</div>
</template> <script>
// 1、定义路由跳转的组件模板
const header = {
template: '<div class="header"> header </div>'
} const sidebar = {
template: '#sidebar',
data() {
return {
menu: [{
name: 'Form',
url: '/form'
}, {
name: 'Info',
url: '/info'
}]
}
},
} const main = {
template: '#main'
} const form = {
template: '#form',
data() {
return {
email: '',
password: ''
}
},
methods: {
submit() {
this.$router.push({
path: '/info?email=' + this.email + '&password=' + this.password
})
}
},
} const info = {
template: '#info'
} // 2、定义路由信息
const routes = [{
path: '/',
components: {
default: header,
sidebar: sidebar,
main: main
},
children: [{
path: '',
redirect: 'form'
}, {
path: 'form',
component: form
}, {
path: 'info',
component: info
}]
}] const router = new VueRouter({
routes
}) // 3、挂载到当前 Vue 实例上
const vm = new Vue({
el: '#app',
data: {},
methods: {},
router: router
});
</script>
3.2、param 传参
与获取 query 参数的方式相同,我们同样可以通过 vm.$route 获取到当前路由信息,从而在 param 对象中通过 $route.params.参数名 的方式获取到通过 param 的方式进行参数传递的值。
不过,与 query 查询参数传参不同的是,在定义路由信息时,我们需要以占位符(:参数名)的方式将需要传递的参数指定到路由地址中,实现代码如下。
const routes = [{
path: '/',
components: {
default: header,
sidebar: sidebar,
main: main
},
children: [{
path: '',
redirect: 'form'
}, {
path: 'form',
name: 'form',
component: form
}, {
path: 'info/:email/:password',
name: 'info',
component: info
}]
}]
因为在使用 $route.push 进行路由跳转时,如果提供了 path 属性,则对象中的 params 属性会被忽略,所以这里我们可以采用命名路由的方式进行跳转或者直接将参数值传递到路由 path 路径中。同时,与使用 query 查询参数传递参数不同,这里的参数如果不进行赋值的话,就无法与我们的匹配规则对应,也就无法跳转到指定的路由地址中。
const form = {
template: '#form',
data() {
return {
email: '',
password: ''
}
},
methods: {
submit() {
// 方式1
this.$router.push({
name: 'info',
params: {
email: this.email,
password: this.password
}
}) // 方式2
this.$router.push({
path: `/info/${this.email}/${this.password}`,
})
}
},
}
其余的部分与使用 query 查询参数传参的方式相同,这里我就直接给出实现代码了,实现的示意图如下。
<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">
<div>
<ul>
<router-link v-for="(item,index) in menu" :key="index" :to="{name:item.routeName}" tag="li">
{{item.displayName}}
</router-link>
</ul>
</div>
</template> <template id="main">
<div>
<router-view> </router-view>
</div>
</template> <template id="form">
<div>
<form>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp"
placeholder="Enter email" v-model="email">
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone
else.</small>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password"
v-model="password">
</div>
<button type="submit" class="btn btn-primary" @click="submit">Submit</button>
</form>
</div>
</template> <template id="info">
<div class="card" style="margin-top: 5px;">
<div class="card-header">
输入的信息
</div>
<div class="card-body">
<blockquote class="blockquote mb-0">
<p>Email Address:{{ $route.params.email }} </p>
<p>Password:{{ $route.params.password }}</p>
<footer class="blockquote-footer">Someone famous in <cite title="Source Title">Source Title</cite>
</footer>
</blockquote>
</div>
</div>
</template> <script>
// 1、定义路由跳转的组件模板
const header = {
template: '<div class="header"> header </div>'
} const sidebar = {
template: '#sidebar',
data() {
return {
menu: [{
displayName: 'Form',
routeName: 'form'
}, {
displayName: 'Info',
routeName: 'info'
}]
}
},
} const main = {
template: '#main'
} const form = {
template: '#form',
data() {
return {
email: '',
password: ''
}
},
methods: {
submit() {
// 方式1
this.$router.push({
name: 'info',
params: {
email: this.email,
password: this.password
}
}) // 方式2
// this.$router.push({
// path: `/info/${this.email}/${this.password}`,
// })
}
},
} const info = {
template: '#info'
} // 2、定义路由信息
const routes = [{
path: '/',
components: {
default: header,
sidebar: sidebar,
main: main
},
children: [{
path: '',
redirect: 'form'
}, {
path: 'form',
name: 'form',
component: form
}, {
path: 'info/:email/:password',
name: 'info',
component: info
}]
}] const router = new VueRouter({
routes
}) // 3、挂载到当前 Vue 实例上
const vm = new Vue({
el: '#app',
data: {},
methods: {},
router: router
});
</script>
三、总结
这一章主要是介绍了命名路由,以及如何通过使用命名视图在 Vue Router 中将多个组件对应到同一个路由。同时,针对实际使用中我们经常会遇到的路由传参,我们则可以通过 query 或者是 param 的方式进行参数传递。不过,不知道你有没有注意到,不管是 query 传参还是 param 传参,最终我们都是通过 vm.$route 属性获取到参数信息,这无疑意味着组件和路由耦合到了一块,所有需要获取参数值的地方都需要加载 Vue Router,这其实是很不应该的,因此如何实现组件与路由间的解耦,我将在下一章中进行说明。
四、参考
[Vue 牛刀小试]:第十三章 - Vue Router 基础使用再探(命名路由、命名视图、路由传参)的更多相关文章
- Vue.js 第1章 Vue常用指令学习
今日目标 能够写出第一个vue应用程序 能够接受为什么需要学vue 能够使用指令 能够通过指定完成简单的业务(增加删除查询) 能够理解mvvm 为什么要学习vue 企业需要 可以提高开发效率 实现vu ...
- vue 路由跳转,传参
一.直接跳转 //js1.this.$router.push('/ad_new') //html 2.<router-link to="/ad_check"> < ...
- Vue学习笔记十三:Vue+Bootstrap+vue-resource从接口获取数据库数据
目录 前言 SpringBoot提供后端接口 Entity类 JPA操作接口 配置文件 数据库表自动映射,添加数据 写提供数据的接口 跨域问题 前端修改 效果图 待续 前言 Vue学习笔记九的列表案例 ...
- vue $emit 父组件与子组件之间的通信(父组件向子组件传参)
1.首先新建一个子页面为 env.vue的文件(名字这里大家可以自取) 2.然后把子页面引入父页面,代码如图: import env from '@/components/common/env' ex ...
- vue 和 react 路由跳转和传参
react 1 .跳转方式加传参 this.props.history.push({ //地址 pathname: '/film/Details', //路由传参 ...
- 【C#基础概念】函数参数默认值和指定传参和方法参数
函数参数默认值和指定传参 最近在编写代码时发现介绍C#参数默认值不能像PL/SQL那样直接设置default,网上也没有太多详细的资料,自己琢磨并试验后整理成果如下: C#允许在函数声明部分定义默认值 ...
- [Vue 牛刀小试]:第十四章 - 编程式导航与实现组件与 Vue Router 之间的解耦
一.前言 在上一章的学习中,通过举例说明,我们了解了 Vue Router 中命名路由.命名视图的使用方法,以及如何通过 query 查询参数传参,或者是采用 param 传参的方式实现路由间的参数传 ...
- Vue的Router路由传参
一.文件结构 二.vue.js 打开此链接 https://cdn.bootcss.com/vue/2.6.10/vue.js 复制粘贴页面的所有内容 三.vue-router.js 打开此链接 h ...
- 从 Vue 的视角学 React(四)—— 组件传参
组件化开发的时候,参数传递是非常关键的环节 哪些参数放在组件内部管理,哪些参数由父组件传入,哪些状态需要反馈给父组件,都需要在设计组件的时候想清楚 但实现这些交互的基础,是明白组件之间参数传递的方式, ...
随机推荐
- Day 10 面向对象基础
目录 面对过程编程 面向对象编程 类 定义类 对象 定义对象 定制对象独有特征 面对过程编程 分析解决问题所需要的步骤, 用函数将这些步骤一步一步实现, 使用的时候一个个调用就可以了 优点: 复杂的问 ...
- 【Nodejs】375- 如何加快 Node.js 应用的启动速度
我们平时在开发部署 Node.js 应用的过程中,对于应用进程启动的耗时很少有人会关注,大多数的应用 5 分钟左右就可以启动完成,这个过程中会涉及到和集团很多系统的交互,这个耗时看起来也没有什么问题. ...
- mini_magick上传图片
rails上传图片需要用到的gem: gem 'carrierwave'gem 'mini_magick' 在项目Gemfil中添加上面的两个gem,然后bundle install 然后创建modl ...
- Python的小整数池
此处经常会作为面试题!!! 小整数池目的:节省内存,提高执行效率 需要注意的是:Python实现int的时候有个小整数池.为了避免因创建相同的值而重复申请内存空间所带来的效率问题, Python解释器 ...
- 【前端学习】网页tab键的实现 01
友情提醒:阅读本文需要了解一些基本的html/Css/Javascript知识 前端常用tab键的实现,用到的原理是当点击一个元素时,通过javascript操作css的display属性,达到控制另 ...
- 视频分享慕课网----Angular 打造企业级协作平台
慕课网是一个非常不错的视频学习网站,搭建搭建企业协作平台,导师由深到浅,讲解的特别好. 本课程主要学习 Angular 进阶知识点和技巧(Material.动画.依赖注入.表单控件.RxJS,Redu ...
- Castle DynamicProxy基本用法(AOP)
本文介绍AOP编程的基本概念.Castle DynamicProxy(DP)的基本用法,使用第三方扩展实现对异步(async)的支持,结合Autofac演示如何实现AOP编程. AOP 百科中关于AO ...
- python接口测试中常见的两种接口依赖处理方式
一.请求体的字段依赖 这种情况多数是在当前测试的接口,它的前置接口的请求体中的字段要拿来在当前的接口请求体中继续使用,比如修改用户信息的接口,该接口会使用到用户名的字段,该字段是由创建用户时的请求体中 ...
- css实现图片动画效果
需求 项目里有个消息中心,当有消息的时候,小铃铛图标可以晃两下,提示当前有信息. 实现过程 书写css 使用css的keyframe属性,配合animation. @keyframes ringing ...
- 为什么delete后磁盘空间没有释放而truncate会释放?
背景 因项目需求,需要清理一批旧数据,腾出空间给新数据,让同事负责这件事.料想会很顺利,但很快找到我,并告知在postgresql中把一张大的数据表删除掉了,查询表的size并没有改变. 我震惊了,问 ...