一、父子组件通信
1、父组件向子组件传值,通过props传值。
父组件代码:
<template>
<div class="section">
<child :list="list"></child>
</div>
</template>
<script>
import child from './child.vue'
export default {
components: { child },
data() {
return {
list: ['a1', 'b2', 'c3']
}
}
}
</script>
子组件的代码(即 child.vue):
<template>
<div>
<span v-for="(item, index) in list" :key="index">{{item}}</span>
</div>
</template>
<script>
export default {
props: ['list'],//用法一
/*props:{
list:{
type:'Array',
default:[]
}
}*/ //用法二
}
</script>
props支持的类型有:String、Number、 Boolean、 Array、Object、Function、 Promise
2、子组件向父组件传值,通过$emit 绑定自定义事件
父组件的代码:
<template>
<div class="section">
<child :list="list" @onEmitIndex="onEmitIndex"></child>
<p>这里是子组件传递:{{chilInfo.item}}-{{chilInfo.index}}</p>
</div>
</template>
<script>
import child from './child.vue'
export default {
components: { child },
data() {
return {
chilInfo:{},
list: ['a1', 'b2', 'c3']
}
},
methods: {
onEmitIndex(arg) {
this.chilInfo= arg;
}
}
}
</script>
子组件的代码(即 child.vue):
<template>
<div>
<button v-for="(item, index) in list" :key="index" @click="emitIndex(index, item)">{{item}}</button>
</div>
</template>
<script>
export default {
props: ['list'],
methods: {
emitIndex(index, item) {
this.$emit('onEmitIndex', {index, item})
}
}
}
</script>
3、通过ref/refs实现父子组件通信
ref 如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例,可以通过实例直接调用组件的方法或访问数据。也算是子组件向父组件传值的一种。
父组件代码:
<template>
<div>
<button @click="sayHello">sayHello</button>
<child ref="childForRef"></child>
</div>
</template>
<script>
import child from './child.vue'
export default {
components: { child },
data () {
return {
}
},
mounted() {
console.log(this.$refs.childForRef.name);
// this.childForRef.sayHello();
},
methods: {
sayHello() {
this.$refs.childForRef.sayHello()
}
}
}
</script>
子组件的代码(即 child.vue):
<template>
<div>child 的内容</div>
</template>
<script>
export default {
data () {
return {
name: '我是 child',
}
},
methods: {
sayHello () {
console.log('hello');
}
}
}
</script>
4、通过children/parent实现父子组件传值
父组件代码:
<template>
<div>
<div>{{msg}}</div>
<child></child>
<button @click="changeA">点击改变子组件值</button>
</div>
</template>
<script>
import Child from './child'
export default {
components: { Child },
data() {
return {
msg: 'Welcome'
}
},
methods: {
changeA() {
this.$children[0].messageA = '这是新的数据'
}
}
}
</script>
子组件的代码(即 child.vue):
<template>
<div class="com_a">
<span>{{messageA}}</span>
<p>获取父组件的值为: {{parentVal}}</p>
</div>
</template>
<script>
export default {
data() {
return {
messageA: '这是老数据'
}
},
computed:{
parentVal(){
return this.$parent.msg;
}
}
}
</script>
二、兄弟组件通信、跨级组件通信
1、通过eventBus实现兄弟、跨级组件通信
eventBus 又称为事件总线,在 vue 中可以使用它来作为沟通桥梁的概念, 就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件, 所以组件都可以通知其他组件。一般用来兄弟组件和隔代组件传值。
使用eventBus首先需要创建一个事件总线并将其导出
bus.js:
import Vue from ‘vue’
export const bus = new Vue()
发送事件,child1、child2 两个兄弟组件,在 child1.vue 中使用bus.$emit()发送事件。
父组件代码:
<template>
<div>
<child1></child1>
<child2></child2>
</div>
</template>
<script>
import child1 from './child1.vue'
import child2 from './child2.vue'
export default {
components: { child1, child2 }
}
</script>
child1.vue代码:
<template>
<div>
<button @click="additionHandle">+加法器</button>
</div>
</template>
<script>
import {bus} from '@/bus.js'
// console.log(bus)
export default {
data(){
return{
num:1
}
},
methods:{
additionHandle(){
bus.$emit('addition', {
num:this.num++
})
}
}
}
</script>
在 child2.vue 中使用bus.$on()接收事件
<template>
<div>计算和: <br>child1Num => {{child1Num}}<br>count + child1Num => {{count}}</div>
</template>
<script>
import { bus } from '@/bus.js'
export default {
data() {
return {
child1Num: 0,
count: 0,
}
},
mounted() {
bus.$on('addition', arg=> {
this.child1Num = arg.num;
this.count = this.count + arg.num;
})
}
}
</script>
如果想移除事件的监听, 可以像下面这样操作:
import { bus } from './bus.js'
bus.$off('addition', {})
2、通过Vuex状态管理实现兄弟、跨级组件通信
vuex的 store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
// 初始化A和B组件的数据,等待获取
AMsg: '',
BMsg: ''
}
const mutations = {
receiveAMsg(state, payload) {
// 将A组件的数据存放于state
state.AMsg = payload.AMsg
},
receiveBMsg(state, payload) {
// 将B组件的数据存放于state
state.BMsg = payload.BMsg
}
}
export default new Vuex.Store({
state,
mutations
})
然后需要在 main.js 中引入 vuex
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store';
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
父组件代码:
<template>
<div id="app">
<child1 />
<child2 />
</div>
</template>
<script>
import child1 from './Child1'
import child2 from './Child2'
export default {
name: 'App',
components: {child1, child2}
}
</script>
child1.vue代码:
<template>
<div id="childA">
<h1>我是1组件</h1>
<button @click="transform">点我让2组件接收到数据</button>
<p>因为你点了2,所以我的信息发生了变化:{{BMessage}}</p>
</div>
</template>
<script>
export default {
data() {
return {
AMessage: 'Hello,2组件,我是1组件'
}
},
computed: {
BMessage() {
// 这里存储从store里获取的2组件的数据
return this.$store.state.BMsg
}
},
methods: {
transform() {
// 触发receiveAMsg,将1组件的数据存放到store里去
this.$store.commit('receiveAMsg', {
AMsg: this.AMessage
})
}
}
}
</script>
child2.vue代码:
<template>
<div id="childB">
<h1>我是2组件</h1>
<button @click="transform">点我让1组件接收到数据</button>
<p>因为你点了1,所以我的信息发生了变化:{{AMessage}}</p>
</div>
</template>
<script>
export default {
data() {
return {
BMessage: 'Hello,1组件,我是2组件'
}
},
computed: {
AMessage() {
// 这里存储从store里获取的1组件的数据
return this.$store.state.AMsg
}
},
methods: {
transform() {
// 触发receiveBMsg,将2组件的数据存放到store里去
this.$store.commit('receiveBMsg', {
BMsg: this.BMessage
})
}
}
}
</script>
除此之外还有prvide、inject等可以实现组件通信,在这就不详细讲解了,有想了解的可以自己查询相关资料了解。