看了很多关于vue组件传值的文章,于是想把文章总结一下,把关于vue组件传值好好聊聊,欢迎大家指正。
组件之间传值主要分两种
1、父子组件:props方法、ref方法、children和parent方法、 emit方法
2、非父子组件:公共bus.js、attrs/listeners、vuex
一、父子组件传值
1、props方法
父组件嵌套的子组件中,使用v-bind:msg=‘xxxx’进行对象的绑定,子组件中通过定义props接收对应的msg对象
父组件
<template>
<div>
<child v-bind:msg="msg" ></child>
</div>
</template>
<script>
// 引入子组件
import child from './child'
export default {
components: {
child,
},
data () {
return {
msg: '父组件传给值'
}
},
}
</script>
子组件
<template>
<div>
<h5>{{msg}}</h5>
</div>
</template>
<script>
export default {
// 要接受父组件传递的参数,在 props 中添加了元素之后,就不需要在 data 中再添加变量了
props: {
msg: {
type: String
},
},
}
</script>
2、$ref方法
使用ref方法获取指定的子组件,使父组件轻松获取子组件的值,
父组件
<template>
<div>
<p>{{msg2}}</p>
<child ref="child"></child>
</div>
</template>
<script>
// 引入子组件
import child from './child'
export default {
components: {
child
},
data() {
return {
msg2: this.$refs.child.msg2
}
}
}
</script>
子组件
<template>
<div>
<h5>{{msg2}}</h5>
</div>
</template>
<script>
export default {
data(){
return{
msg2: "子组件传给父组件"
}
}
}
</script>
3、children,parent方法
使用 parent 查找当前组件的父组件。
使用 this.$children 查找当前组件的直接子组件,可以遍历全部子组件, 需要注意 $children 并不保证顺序,也不是响应式的,故不推荐使用。
父组件
<template>
<div>
<h1>{{msg2}}</h1>
<child :msg2="msg2"></child>
</div>
</template>
<script>
// 引入子组件
import child from './child'
export default {
components: {
child
},
data() {
return {
msg: "父组件传给子组件",
msg2: ""
}
},
mounted(){
// 注意,this.$children[0].msg2只能在mounted生命周期下面才能获取,否则会报错
this.msg2 = this.$children[0].msg2
}
}
</script>
子组件
<template>
<div>
<h5>{{msg}}</h5>
</div>
</template>
<script>
export default {
data(){
return{
msg2: "子组件传给父组件",
msg: this.$parent.msg
}
}
}
</script>
4、emit方法
子组件使用emit触发父组件的自定义事件:
vm.$emit( event, arg ) //触发当前实例上的事件
vm.$on( event, fn ) //监听event事件后运行 fn
父组件
<template>
<div>
<h1>{{msg2}}</h1>
<child @eventName="changeMsg"></child>
</div>
</template>
<script>
// 引入子组件
import child from './child'
export default {
components: {
child
},
data() {
return {
msg2: "父组件的值",
}
},
methods:{
//changeMsg是自定义方法名,msg是子组件传过来的参数
changeMsg(msg){
this.msg2 = msg
}
}
}
</script>
子组件
<template>
<div>
<button @click="open">请点击</button>
</div>
</template>
<script>
export default {
data(){
return{
msg: "子组件传给父组件"
}
},
methods: {
open(){
//eventName是父组件的自定义方法名,this.msg是传过去的参数
this.$emit('eventName', this.msg)
}
}
}
</script>
二、非父子组件传值
1、公共的bus.js
1、兄弟之间传递数据需要借助于事件车,通过事件车的方式传递数据。
2、创建一个Vue的实例,让各个兄弟共用同一个事件机制。
3、传递数据方,通过一个事件触发bus.$emit(方法名,传递的数据)。
4、接收数据方,通过mounted(){}触发bus.$on (方法名,function(接收数据的参数){用该组件的数据接收传递过来的数据}),此时函数中的this已经发生了改变,可以使用箭头函数。
bus.js
import Vue from 'vue'
export default new Vue
公共组件存放兄弟组件
<template>
<div>
<list1></list1>
<list2></list2>
</div>
</template>
<script>
import list1 from './list1'
import list2 from './list2'
export default {
components:{
list1,
list2
}
}
</script>
兄弟组件1
<template>
<div>
<h1>{{msg}}</h1>
<button @click="trans">把值传给小弟</button>
</div>
</template>
<script>
import bus from "./bus"
export default {
data() {
return {
msg: "大哥组件的值传给小弟",
}
},
methods:{
trans(){
bus.$emit('eventName', this.msg)
}
}
}
</script>
兄弟组件2
<template>
<div>
<h5>{{msg}}</h5>
</div>
</template>
<script>
import bus from "./bus"
export default {
data() {
return {
msg: "小弟组件的值",
}
},
mounted(){
bus.$on('eventName', val =>{
this.msg = val;
})
}
}
</script>
2、attrs和listeners的使用
在很多开发情况下,我们只是想把A组件的信息传递给C组件,如果使用props 绑定来进行信息的传递,虽然能够实现,但是代码并不美观。
在vue2.4中,为了解决该需求,引入了attrs 和listeners , 新增了inheritAttrs 选项。
在版本2.4以前,默认情况下父作用域的不被认作props的属性,将会“回退”且作为普通的HTML特性应用在子组件的根元素上。
$attrs
包含了父作用域中不被认为 (且不预期为) props 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 props 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind=”$attrs” 传入内部组件——在创建更高层次的组件时非常有用。
$listeners
包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=”$listeners” 传入内部组件——在创建更高层次的组件时非常有用。
inheritAttrs
默认情况下父作用域的不被认作 props 的特性绑定 (attribute bindings) 将会“回退”且作为普通的 HTML 特性应用在子组件的根元素上。当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。通过设置 inheritAttrs 到 false,这些默认行为将会被去掉。而通过 (同样是 2.4 新增的) 实例属性 $attrs 可以让这些特性生效,且可以通过 v-bind 显性的绑定到非根元素上。
A组件
<template>
<div id="app">
<!-- 此处监听了两个事件,可以在B组件或者C组件中直接触发 -->
<child1 :p-child1="child1" :p-child2="child2" v-on:test1="onTest1" v-on:test2="onTest2"></child1>
</div>
</template>
<script>
import Child1 from './Child1.vue'
export default {
data() {
return {}
},
components: { Child1 },
methods: {
onTest1() {
console.log('test1 running...')
},
onTest2() {
console.log('test2 running')
}
}
}
</script>
B组件
<template>
<div class="child-1">
<p>in child1:</p>
<p>props: {{pChild1}}</p>
<p>$attrs: {{$attrs}}</p>
<hr />
<!-- C组件中能直接触发test的原因在于 B组件调用C组件时 使用 v-on 绑定了$listeners 属性 -->
<!-- 通过v-bind 绑定$attrs属性,C组件可以直接获取到A组件中传递下来的props(除了B组件中props声明的) -->
<child2 v-bind="$attrs" v-on="$listeners"></child2>
</div>
</template>
<script>
import Child2 from './Child2'
export default {
props: ['pChild1'],
data() {
return {}
},
inheritAttrs: false,
components: { Child2 },
mounted() {
this.$emit('test1')
}
}
</script>
C组件
<template>
<div class="child-2">
<p>in child2:</p>
<p>props: {{pChild2}}</p>
<p>$attrs: {{$attrs}}</p>
<hr />
</div>
</template>
<script>
export default {
props: ['pChild2'],
data() {
return {}
},
inheritAttrs: false,
mounted() {
this.$emit('test2')
}
}
</script>
3、vuex
vuex是我们开发中最常用的一种跨组件传值方式,下期我们单独聊聊vuex。以上就是vue组件传值常用的几种方式,如有错误,欢迎指正。