Vue传参一箩筐(页面、组件)


Posted in Javascript onApril 04, 2019

Vue页面、组件之间传参方式繁多,此处罗列出常用的几种方式,欢迎审阅补充。

一丶路由传参

这里的路由传参以编程式 router.push(...) 为例,声明式 <router-link :to="..."> 与之类似。此处模拟情景为从 componentsA.vue 页面跳转到 componentsB.vue 页面传参。首先,路由配置信息如下:

router.js

import Vue from 'vue'
import Router from 'vue-router'

import componentsA from './components/componentsA' //在components下创建componentsA.vue
import componentsB from './components/componentsB' //在components下创建componentsB.vue
Vue.use(Router)

export default new Router({
	routes:[
		{
			path:'/componentsA',
			name:'componentsA',
			component:componentsA
		},
		{
			path:'/componentsB',
			name:'componentsB',
			component:componentsB
		}
	]
})

1.1 路由配置传参

首先确定自己要传的参数名,将路由配置修改一下,传name,age,sex三个参数:

{
			path:'/componentsB/:name/:age/:sex',
			name:'componentsB',
			component:componentsB
		}

componentsA.vue 页面通过 this.$router.push 配置与之对应的参数:

componentsA.vue

<template>
	<div>
		<div>我是组件A</div>
		<button @click='routerToB1'>方式一跳转到组件B</button>
	</div>
</template>
<script>
	export default{
		data(){
			return{
				person:{name:'Gene',age:'18',sex:'male'}
			}
		},
		methods: {
			routerToB1() {
				this.$router.push({
					path:`componentsB/${this.person.name}/${this.person.age}/${this.person.sex}`
				})
			}
		},
	}
</script>
<style>
</style>

然后在 componentsB.vue 页面用 this.$route.params 接收参数:

componentsB.vue

<template>
	<div>
		<div>我是组件B</div>
	</div>
</template>
<script>
	export default{
		created(){
			this.getRouterData()
		},
		methods: {
			getRouterData(){
				const param = this.$route.params
				console.log(param)//{name:'Gene',age:'18',sex:'male'}
			}
		},
	}
</script>
<style>
</style>

点击按钮"方式一跳转到组件B",componentsB页面打印出 {name:'Gene',age:'18',sex:'male'} ,成功获取到A页面传过来的参数,并且地址栏显示为 localhost:8889/#/componentsB/Gene/18/male (端口号根据自己设置的来),表明这种传参方式url会携带参数。

1.2 params传参

首先将刚才路由配置修改部分还原,在 componentsA.vue 页面添加按钮"方式二跳转到组件B":

componentsA.vue

<template>
	<div>
		<div>我是组件A</div>
		<button @click='routerToB1'>方式一跳转到组件B</button>
		<button @click='routerToB2'>方式二跳转到组件B</button>
	</div>
</template>

methods 中添加方法 routerToB2 ,使用路由属性 name 来确定匹配的路由,使用属性 params 来传递参数:

componentsA.vue

routerToB2(){
				this.$router.push({
					name:'componentsB',
					params:{
						exa:'我是传到组件B的参数'
					}
				})
			},

componentsB.vue 保持不变,params传参方式获取参数也是通过 this.$route.params ,点击A页面新添加的按钮"方式二跳转到组件B",在B页面打印出 {exa: "我是传到组件B的参数"} ,传参成功,地址栏为 localhost:8889/#/componentsB ,表明这种方式url不会携带参数。

1.3 query传参

这种方式和params传参方式类似,在 componentsA.vue 页面继续添加按钮"方式三跳转到组件B":

componentsA.vue

<template>
	<div>
		<div>我是组件A</div>
		<button @click='routerToB1'>方式一跳转到组件B</button>
		<button @click='routerToB2'>方式二跳转到组件B</button>
		<button @click='routerToB3'>方式三跳转到组件B</button>
	</div>
</template>

methods 中添加方法 routerToB3 ,使用路由属性 name 或者 path 来确定匹配的路由,使用属性 query 来传参:

componentsA.vue

routerToB3(){
				this.$router.push({
					name:'componentsB',// path:'/componentsB'
					query:{
						que:'我是通过query传到组件B的参数'
					}
				})
			}

componentsB.vue 页面通过 this.$route.query 来获取参数:

componentsB.vue

getRouterData(){
				const query = this.$route.query
				console.log(query)//{que: "我是通过query传到组件B的参数"}
			}

查看地址栏为 localhost:8889/#/componentsB?que=我是通过query传到组件B的参数 ,显然这种方式url会携带参数。

1.4 小结

  • 路由配置传参注意书写格式 /:id ,获取参数都是通过 $route 而不是 $router
  • params 传参和 query 传参区别类似于 postget 方法。 params 传参地址栏不会显示参数,而 query 传参会将参数显示在地址栏中
  • params 传参刷新页面参数会丢失,另外两种不会
  • params 传参对应的路由属性是 name ,而 query 传参对应的路由属性既可以是 name ,也可以是 path

二丶使用缓存

缓存方式即通过 sessionStoragelocalStorageCookie 方式传参,这种方式和是不是用Vue无关,因此,不谈。

三丶父子组件之间传值

在components目录下创建父组件 parent.vue 和子组件 children.vue ,在父组件中引入子组件。为了演示方便,在路由配置中加入 /parent 路径。

3.1 父组件向子组件传值 props

parent.vue 的子组件标签上注册message1,在 children.vue 中通过 props 接收message1,如果传递的值为变量,则使用 v-bind: 或直接用 : ,参考如下:

parent.vue

<template>
	<div>
		<div>我是父组件</div>
		<children message1='我是直接参数' v-bind:message2='msg' :message3='obj'></children>
	</div>
</template>

<script>
	import Children from './children'
	export default{
		components:{
			Children
		},
		data(){
			return{
				msg:'我是父组件的参数'
			}
		},
		created(){
			this.obj = {a:'1',b:'2',c:'3'}
		}
	}
</script>

<style>
</style>

children.vue

<template>
	<div>
		<div>我是子组件</div>
		<div>{{message1}}</div>
		<div>{{message2}}</div>
		<div>{{message3}}</div>
	</div>
</template>

<script>
	export default{
		props:['message1','message2','message3'],
		created(){
			console.log(this.message3)
		}
	}
</script>

<style>
</style>

在浏览器中打开:

Vue传参一箩筐(页面、组件)

3.2 子组件向父组件传值 $emit

子组件通过vm.$emit( event, […args] ),触发当前实例上的事件。附加参数都会传给监听器回调。父组件在子组件标签上监听事件获得参数。

children.vue

<template>
	<div style="margin-top: 100px;">
		<div>我是子组件</div>
		<div>{{message1}}</div>
		<div>{{message2}}</div>
		<div>{{message3}}</div>
		<button @click='ChildToParent'>点我传爱</button>
	</div>
</template>

<script>
	export default{
		props:['message1','message2','message3'],
		data(){
			return{
				loud:'I love xx'
			}
		},
		methods:{
			ChildToParent(){
				this.$emit('emitToParent',this.loud)
			}
		},
		created(){
			console.log(this.message3)
		}
	}
</script>

<style>
</style>

parent.vue

<template>
	<div>
		<div>我是父组件</div>
		<div>大声告诉我你爱谁:{{loveWho}}</div>
		<children @emitToParent='parentSayLove' message1='我是直接参数' v-bind:message2='msg' :message3='obj'></children>
	</div>
</template>

<script>
	import Children from './children'
	export default{
		components:{
			Children
		},
		data(){
			return{
				msg:'我是父组件的参数',
				loveWho:''
			}
		},
		methods:{
			parentSayLove(data){
				this.loveWho = data
			}
		},
		created(){
			this.obj = {a:'1',b:'2',c:'3'}
		}
	}
</script>

<style>
</style>

点击按钮浏览器显示:

Vue传参一箩筐(页面、组件)

3.3 小结

props 可以是字符串数组,也可以是对象(可以类型验证、设置默认值等) ;

使用 .native 修饰监听事件,开发中使用了 element-ui 的框架标签时候,使用事件绑定无效。这时候需要使用 .native 修饰 v-on:event ,可以在框架标签或组件的根元素 上监听一个原生事件,例如 <my-component v-on:click.native="doTheThing"></my-component>

 四丶非父子(兄弟)组件之间传值

非父子组件之间传值,需要定义公共实例文件 bus.js ,作为中间仓库来传值,不然路由组件之间达不到传值的效果。在components目录下新建 first.vuesecond.vue 以及公共文件 bus.js

bus.js

import Vue from 'vue'
export default new Vue()

first.vuesecond.vue 中分别引入bus.js。

import Bus from '../bus.js'

模拟情景: first.vuesecond.vue 传值。在 first.vue 通过在事件中添加 Bus.$emit( event, […args] ) 进行传值,在 second.vue 中通过 Bus.$on(event,callBack) 进行监听。

first.vue

<template>
	<div>
		<div>我是first.vue</div>
		<button @click="firstToSecond">点击传值给second.vue</button>
	</div>
</template>

<script>
	import Bus from '../bus.js'
	export default{
		data(){
			return{
				msg:'我是first.vue传到second.vue的参数'
			}
		},
		methods:{
			firstToSecond(){
				Bus.$emit('emitToSecond',this.msg)
			}
		}
	}
</script>

<style>
</style>

second.vue

<template>
	<div>
		<div>我是second.vue</div>
		{{info}}
	</div>
</template>

<script>
	import Bus from '../bus.js'
	export default{
		data(){
			return{
				info:''
			}
		},
		mounted(){
			const that = this;
			Bus.$on('emitToSecond',function(data){
				that.info = data
			})
		}
	}
</script>

<style>
</style>

点击按钮,浏览器中显示:

Vue传参一箩筐(页面、组件)

小结

兄弟组件之间与父子组件之间的数据交互,两者相比较,兄弟组件之间的通信其实和子组件向父组件传值有些类似,他们的通信原理都是相同的,例如子向父传值也是 $emit$on 的形式,只是没有 Bus ,但若我们仔细想想,此时父组件其实就充当了 Bus 这个事件总线的角色。

五丶使用Vuex

何为Vuex,看一下官网的解释:

Vuex 是一个专为 Vue.js 应用程序开发的 状态管理模式 。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

Vue传参一箩筐(页面、组件)

什么情况下使用Vuex?

Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。

如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的store 模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。

在components目录下新建 vuexA.vuevuexB.vue ,模拟场景: vuexA.vuevuexB.vue 传值。

首先我们安装vuex, npm install vuex --save ,在src目录下创建vuex目录,然后在vuex目录下新建 index.jsstate.jsgetters.jsactions.jsmutations.js

Vue传参一箩筐(页面、组件)

vuex/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import state from './state.js'
import mutations from './mutations.js'
import getters from './getters.js'
import actions from './actions.js'
Vue.use(Vuex)

export default new Vuex.Store({
	state,
	getters,
	mutations,
	actions
})

在main.js中引入vuex/index.js并注入到Vue中:

main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './vuex'
Vue.config.productionTip = false

new Vue({
	store,
	router,
 render: h => h(App),
}).$mount('#app')

state.js

export default{
	city:'nanjing'
}

vuexA.vue

<template>	
  <div>
		<div>我是vuexA中city参数:{{city}}</div>
		<input type="text" :value="city" @change="change">
	</div>
</template>

<script>
	export default{
		methods:{
			change(e){
				this.$store.dispatch('setCityName',e.target.value)
			}
		},
		computed:{
			city(){
				return this.$store.getters.getCity
			}
		}
	}
</script>

<style>
</style>

vuexB.vue

<template>
	<div>
		<div>我是vuexB中的city参数:{{city}}</div>
	</div>
</template>

<script>
	export default{
		data(){
			return{
				
			}
		},
		computed:{
			city(){
				return this.$store.state.city
			}
		}
	}
</script>

<style>
</style>

actions.js

export default{
	setCityName({commit,state},name){
		commit('setCity',name)
	}
}

mutations.js

export default{
	setCity(state,name){
		state.city = name//设置新的值
	}
}

getter.js

export default{
	getCity(state){
		return state.city//返回目前城市名称
	}
}

在浏览器中打开:

Vue传参一箩筐(页面、组件)

修改input中的值:

Vue传参一箩筐(页面、组件)

显而易见,当vuexA页面中input值改变时,可同时改变vuexB页面中的值,即将city参数从vuexA页面传到了vuexB页面,从而实现用vuex在组件中传值。

vuex更多详细功能请参考Vuex中文官方文档。

全部实例代码已上传至 我的GitHub,欢迎访问Fork。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
基于jquery固定于顶部的导航响应浏览器滚动条事件
Nov 02 Javascript
28个常用JavaScript方法集锦
Jan 14 Javascript
jQuery链式操作实例分析
Nov 16 Javascript
JS实现求数组起始项到终止项之和的方法【基于数组扩展函数】
Jun 13 Javascript
vue音乐播放器插件vue-aplayer的配置及其使用实例详解
Jul 10 Javascript
jq源码解析之绑在$,jQuery上面的方法(实例讲解)
Oct 13 jQuery
jQuery实现使用sort方法对json数据排序的方法
Apr 17 jQuery
代码实例ajax实现点击加载更多数据图片
Oct 12 Javascript
详解Vue 匿名、具名和作用域插槽的使用方法
Apr 22 Javascript
详解vue修改elementUI的分页组件视图没更新问题
Nov 13 Javascript
微信小程序实现底部弹出模态框
Nov 18 Javascript
JavaScript实现班级抽签小程序
May 19 Javascript
Vue使用.sync 实现父子组件的双向绑定数据问题
Apr 04 #Javascript
小程序getLocation需要在app.json中声明permission字段
Apr 04 #Javascript
Vue组件内部实现一个双向数据绑定的实例代码
Apr 04 #Javascript
详解JavaScript的变量
Apr 04 #Javascript
vue elementUI table表格数据 滚动懒加载的实现方法
Apr 04 #Javascript
js 计算图片内点个数的示例代码
Apr 04 #Javascript
在node中使用jwt签发与验证token的方法
Apr 03 #Javascript
You might like
PHP 类型转换函数intval
2009/06/20 PHP
phpmailer中文乱码问题的解决方法
2014/04/22 PHP
Chrome Web App开发小结
2014/09/04 PHP
php计算给定时间之前的函数用法实例
2015/04/03 PHP
PHP微信API接口类
2016/08/22 PHP
PHP 中使用explode()函数切割字符串为数组的示例
2017/05/06 PHP
PHP针对伪静态的注入总结【附asp与Python相关代码】
2017/08/01 PHP
PHP8.0新功能之Match表达式的使用
2020/07/19 PHP
jQuery live( type, fn ) 委派事件实现
2009/10/11 Javascript
jquery checkbox全选、取消全选实现代码
2010/03/05 Javascript
Prototype源码浅析 String部分(四)之补充
2012/01/16 Javascript
CKEditor无法验证的解决方案(js验证+jQuery Validate验证)
2016/05/09 Javascript
JavaScript常见的五种数组去重的方式
2016/12/15 Javascript
js判断一个字符串是以某个字符串开头的简单实例
2016/12/27 Javascript
js获取当前周、上一周、下一周日期
2017/03/19 Javascript
JS正则表达式验证中文字符
2017/05/08 Javascript
jQuery+ajax实现局部刷新的两种方法
2017/06/08 jQuery
67 个节约开发时间的前端开发者的工具、库和资源
2017/09/12 Javascript
React中this丢失的四种解决方法
2019/03/12 Javascript
[56:56]VG vs LGD 2019国际邀请赛淘汰赛 胜者组 BO3 第一场 8.22
2019/09/05 DOTA
Python设置Socket代理及实现远程摄像头控制的例子
2015/11/13 Python
基于python中的TCP及UDP(详解)
2017/11/06 Python
Python实现决策树C4.5算法的示例
2018/05/30 Python
Python使用爬虫抓取美女图片并保存到本地的方法【测试可用】
2018/08/30 Python
Python爬虫小技巧之伪造随机的User-Agent
2018/09/13 Python
Python3的介绍、安装和命令行的认识(推荐)
2018/10/20 Python
Python中的asyncio代码详解
2019/06/10 Python
Python使用numpy模块实现矩阵和列表的连接操作方法
2019/06/26 Python
python 实现将小图片放到另一个较大的白色或黑色背景图片中
2019/12/12 Python
在django中使用apscheduler 执行计划任务的实现方法
2020/02/11 Python
Python3搭建http服务器的实现代码
2020/02/11 Python
python asyncio 协程库的使用
2021/01/21 Python
美国电视购物HSN官网:HSN
2016/09/07 全球购物
加拿大时尚少女服装品牌:Garage
2016/10/10 全球购物
PL350与SW11的比较
2021/04/22 无线电
Java实现字符串转为驼峰格式的方法详解
2022/07/07 Java/Android