组件通信概念
Vue中我们所有的页面都是基于组件构造出来,组件之间相互嵌套。父组件、子组件、兄弟组件的说法。
再真实业务开发过程中,我们可能会再父组件中获取数据,交给子组件渲染。获取到父组件传递给他的数据,就这种流程称为组件通信
父组件传递数据给子组件,子组件传递数据给父组件
父子组件通信
可以接受外部数据,组件数据由两部分组成,内部data定义,另外一部分就外部props定义
父组件
<template>
<div>
<TabA :array="list" index="no1" :idx="1" :boo="true"></TabA>
</div>
</template>
<script>
import TabA from "./TabA.vue"
export default {
data() {
return {
list: [
{ id: 1, title: "流行歌曲" },
{ id: 2, title: "网络歌曲" },
{ id: 3, title: "emo歌曲" },
],
};
},
components:{
TabA
}
};
</script>
<style>
</style>
子组件代码
<template>
<div>
<div class="linebox">
<ul>
<li v-for="item in array" :key="item.id">{{item.title}}</li>
</ul>
<p>{{index}}</p>
<p>{{idx}}</p>
</div>
</div>
</template>
<script>
export default {
// 组件外部数据
props:["array","index","idx"],
// 组件内部数据
data(){
return{
}
}
}
</script>
<style scoped lang="scss">
.linebox{
width: 100px;
height: 100px;
border: 1px solid red;
}
</style>
父组件传递数据的时候,可以动态数据,也可以静态数据。
传递数据的要求数据类型,加上冒号来传递
字符串除外
子组件获取数据
props:[变量1,变量2]
自己再封装一个组件的时候,接受外部数据,需要对外部数据进行校验,如果按照你的要求来传递数据,默认能完整显示,否则抛出警告,甚至报错
简单的验证
export default {
props:{
list:Array
money:Number
}
}
设置数据类型和默认值
export default {
props:{
list:{
type:[Array,Number],
default:[]
}
}
}
可以接受多个数据类型,如果外部没有传递采用default默认值,外部传递数据,传递的值来渲染
也是Vue提供的一个函数,可以实现再子组件里面传递参数给父组件
子组件可以调用父组件的提供的一个函数。
父组件定义一个函数
methods:{
changePlay(index){
console.log(index);
this.list[index].play = !this.list[index].play
}
}
父组件自定义一个事件,将函数传递过去
<TabA :array="list" @wantChangePlay="changePlay"></TabA>
@wantChangePlay:就是自定义的事件,事件名字自己取,子组件调用的时候就用这个名字
子组件调用
<div class="linebox" v-for="(item,index) in array" :key="item.id">
<p>{{item.title}}</p>
<p>{{item.play?"正在播放":"暂停播放"}}</p>
<button @click="$emit('wantChangePlay',index)">播放</button>
</div>
子组件通过$emit函数来调用父组件传的事件名字,触发父组件的函数,就可以将参数传递回父组件
父组件完整代码
<template>
<div>
<TabA :array="list" index="no1" :idx="1" :boo="true" @wantChangePlay="changePlay"></TabA>
</div>
</template>
<script>
import TabA from "./TabA.vue"
import TabB from "./TabB.vue"
export default {
data() {
return {
list: [
{ id: 1, title: "流行歌曲",play:false },
{ id: 2, title: "网络歌曲",play:false },
{ id: 3, title: "emo歌曲" ,play:false},
],
};
},
components:{
TabA,TabB
},
methods:{
changePlay(index){
console.log(index);
this.list[index].play = !this.list[index].play
}
}
};
</script>
<style>
</style>
子组件完整代码
<template>
<div>
<div class="linebox" v-for="(item,index) in array" :key="item.id">
<p>{{item.title}}</p>
<p>{{item.play?"正在播放":"暂停播放"}}</p>
<button @click="$emit('wantChangePlay',index)">播放</button>
</div>
</div>
</template>
<script>
export default {
// 组件外部数据
props:["array","index","idx"],
// 组件内部数据
data(){
return{
}
}
}
</script>
<style scoped lang="scss">
.linebox{
width: 200px;
height: 200px;
border: 1px solid red;
}
</style>
兄弟组件通信
Vue组件中如果遇到兄弟组件要传递值,目前我们的方案,将子组件的数据传递父组件,让父组件传递另外一个子组件。
如果遇到两个组件他们离得比较远,父组件来实现传值,就比较麻烦
再Vue中提供了事件总线来实现兄弟组件传递值(任何两个组件之间都可以通信)
事件总线原理:
在事件总线中,核心的原理就是一个组件绑定一个监听器。另外一个组件触发这个监听器。实现两个组件之间通信。
比如A组件要传递数据给B组件,B组件首先要在Bus上面绑定一个监听器。A组件来触发这个监听器。
事件总线任何两个组件之间都可以实现参数传递
场景一:A组件传递参数给B组件
bus总线
在项目中创建一个bus.js文件,里面创建Vue对象
import Vue from "vue"
const bus = new Vue
export default bus
B组件:
<template>
<div>
<h1>b组件</h1>
</div>
</template>
<script>
import bus from "./bus"
export default {
mounted(){
// 在全局对象中(bus)注册一个监听器
// getData代表事件的名字
bus.$on("getData",data=>{
console.log("B组件接受的数据:",data);
})
}
}
</script>
<style>
</style>
A组件:
<template>
<div>
<button @click="sendMessage">传递参数给B组件</button>
</div>
</template>
<script>
import bus from "./bus"
export default {
data(){
return{
msg:"蜗牛"
}
},
methods:{
sendMessage(){
// 触发bus里面的某一个监听器
bus.$emit("getData",this.msg)
}
}
}
</script>
<style>
</style>
bus.$on()代表给Vue对象动态绑定事件
bus.$emit()执行绑定的自定义事件,和父组组件传递参数是一样的。
学习Vuex过后,我们还可以用Vuex来进行组件值传递