Vue作为一个轻量级的前端框架,它的核心就是组件化开发。Vue是由一个一个组件构成,各个组件实例的作用域之间相互独立,就造成了不同组件之间的数据不能相互引用。然而,在实际开发中,需要访问其他组件中的数据时,就有了组件之间数据传递的问题。
Vue各组件之间的关系有:父子关系、兄弟关系、隔代关系。
那他们之间是怎样进行数据传输的,这就是接下来要讲述的问题。
1.父组件给子组件传值:
方案:使用自定义属性
在子组件里面定义一个props自定义属性,在父组件中以标签的形式使用注册的子组件时,把数据通过v-bind绑定给子组件Left.vue
父组件:App.vue
<template>
<div class="app-container">
<h1>App 根组件</h1>
<hr />
<div class="box">
<!-- 在以标签的形式使用注册的组件时,把数据通过v-bind绑定给子组件 -->
<Left :msg="message"></Left>
</div>
</div>
</template>
<script>
import Left from '@/components/Left.vue'
export default {
// 在父组件的data里面存的数据,将来要传给子组件Left.vue
data() {
return {
message:'hello vue.js'
}
},
components: {
Left
}
}
</script>
子组件:Left.vue
<template>
<div class="left-container">
<!-- 在子组件中使用父组件传递过来的值 -->
<h3>Left 组件--父组件传过来的值是{{myMsg}}</h3>
</div>
</template>
<script>
export default {
// 在子组件定义一个自定义属性 自定义属性我们开发者自己起名,符合规范即可
// 这里msg可以是基本数据类型也可以是对象
// props: ['msg']
props: {
msg: {
type: String,
default: ''
}
},
// 需要注意的是,这里的props值是不能修改的,如果想要修改,可以在data里面重新定义一个变量myMsg,并把props的值赋给data
data() {
return {
myMsg:this.msg
}
}
}
</script>
2.子组件给父组件传值:
方案:使用自定义事件
子组件中使用 this.$emit('numChange')触发,父组件使用@numChange监听
子组件:Right.vue
<template>
<div class="right-container">
<h3>Right 组件</h3>
<button @click="add">点击+1---{{count}}</button>
</div>
</template>
<script>
export default {
data() {
return {
count:0
}
},
methods: {
add() {
this.count += 1
// 子组件中使用自定义事件numChange,通过$emit触发
// this.count存了最新的count,用来传递给父组件App.vue
this.$emit('numChange',this.count)
}
}
}
</script>
父组件:App.vue
<template>
<div class="app-container">
<!-- countFromRight展现出子组件传过来的值 -->
<h1>App 根组件--{{countFromRight}}</h1>
<hr />
<div class="box">
<!-- 绑定自定义事件numChange,调用事件处理函数getNewCount -->
<Right @numChange="getNewCount"></Right>
</div>
</div>
</template>
<script>
import Right from '@/components/Right.vue'
export default {
data() {
return {
countFromRight:0
}
},
components: {
Right
},
methods: {
// 事件处理函数getNewCount的形参val用来接收子组件通过$emit传过来的this.count
getNewCount(val) {
this.countFromRight=val
}
}
}
</script>
3.兄弟组件传值:
方案:eventBus
步骤:①创建一个eventBus.js模块,向外共享一个vue的实例对象
②数据发送方:调用bus.$emit('事件名称',要发送的数据)
③数据接收方:调用bus.$on('事件名称',事件处理函数)
eventBus.js:
// 导入vue构造函数
import Vue from 'vue'
// 创建vue实例,并向外共享出去
export default new Vue()
兄弟组件A(数据发送方):
<template>
<div class="right-container">
<h3>Right 组件--</h3>
<button @click="send">点击发送数据</button>
</div>
</template>
<script>
// 导入eventBus模块
import bus from './eventBus.js'
export default {
data() {
return {
// 向外发送的数据
msg:'hello vue'
}
},
methods: {
send() {
// 通过eventbus发送数据 $emit触发share自定义事件
bus.$emit('share',this.msg)
}
}
}
</script>
兄弟组件B(数据接收方):
<template>
<div class="left-container">
<h3>Left 组件---{{msgFromRight}}</h3>
</div>
</template>
<script>
// 导入eventBus模块
import bus from './eventBus.js'
export default {
props: {
},
data() {
return {
// 把接受来的数据存到msgFromRight
msgFromRight:''
}
},
created() {
// val代表Right.vue的传递过来的数据 并用msgFromRight来接收
bus.$on('share', val => {
this.msgFromRight=val
})
}
}
</script>
这里用bus.$emit而不用this.$emit,是因为this在各自组件中,指向的是各自组件的实例对象,而不是同一个。$emit和$on都通过bus调用,此时bus指向的是同一个vue实例。