vue父子组件通信

Posted by     小兵兵 on Tuesday, March 24, 2020

目录

vue父子组件通信

父组件使用子组件

创建子组件

<template>
    <div>
      
    </div>
</template>

<script>
    export default {
        name: "xxx"
    }
</script>

<style scoped>

</style>

声明子组件需要的数据(属性、方法)

props: {
      /*      show: {
                type: Boolean,
                default: false
            },
            orderType: '',*/
            param: {
                method:{
                    type:Function,
                    default:null
                }
            }
        },

父组件导入子组件、挂载子组件

import myDialog from '../commonviews/My_Dialog'
export default {
	components:{
			myDialog
		}
}

传递数据给子组件(属性、方法)

import myDialog from '../commonviews/My_Dialog'
export default {
	components:{
			myDialog
		}
	data() {
			return {
				param:{
					url:addMakeUpInfo,
					orderType:2,
					show:false,
					method:this.getRows  //this.getRows是父组件的方法引用
				}
		 }	
}


<myDialog  :param="param" @callTheParentComponentMethod="resetToCloseTheDialog"></myDialog>

子组件使用父组件数据(属性、方法)

this.param.orderType
this.param.show
this.param.url
this.param.method()

父组件使用子组件数据(属性、方法)

通过ref获得子组件的引用,然后就可以操作子组件的数据(属性、方法),下面讲

父组件操作子组件的数据(属性、方法)

子组件声明数据(属性、方法)

export default {
	data() {
			return {
				 appointType: false
		 }	
	}
	methods: {
            handleParentClick(e) {
               console.info(e)
            }	
	}
}

父组件获取子组件的引用

<myDialog  ref="myDialog" :param="param" @callTheParentComponentMethod="resetToCloseTheDialog"></myDialog>

父组件使用子组件的数据(属性、方法)

this.$refs.myDialog.handleParentClick("aaaaa");
console.log('子组件的属性appointType---------->',this.$refs.myDialog.appointType)

子组件操作父组件的数据(属性、方法)

新增对话框填写表单数据,点击提交按钮,成功的话需要关闭对话框、重新查询一遍列表数据,此时需要调用父组件的列表查询方法、修改对话框显示的状态,该状态是通过父组件传递给子组件的,所以子组件需要调用父组件的方法来修改对话框的状态

方式一

父组件声明

<myDialog :param="param" @callTheParentComponentMethod="resetToCloseTheDialog" @callParentGetRows="getRows"></myDialog>

export default {
	data() {
			return {
				param:{url:addMakeUpInfo,orderType:2,show:false}
		 }	
	}
	methods: {
           resetToCloseTheDialog(formRule){
				// console.log('formRule.addForm.show------->',formRule.show)
				this.param.show=formRule.show
			},
	}
}

子组件使用

this.$emit('callTheParentComponentMethod', {show: false}) 
this.$emit('callParentGetRows')

方式二

子组件使用

this.$parent.param
this.$parent.getRows()

方式三

该方式前面已经讲过,子组件使用

this.param.orderType
this.param.show
this.param.url
this.param.method()

任意组件通信

自定义事件总线

创建myBus.js

// Bus:事件派发、监听和回调管理
class Bus {
    constructor() {
        // {
        //  eventName1:[fn1,fn2],
        //  eventName2:[fn3,fn4],
        // }
        this.callbacks = {}
    }

    $on(name, fn) {
        this.callbacks[name] = this.callbacks[name] || []
        this.callbacks[name].push(fn)
    }

    $emit(name, args) {
        if (this.callbacks[name]) {
            this.callbacks[name].forEach(cb => cb(args))
        }
    }
}
export default Bus

main.js全局挂载

import myBus from './myBus'
Vue.prototype.$bus = new myBus()

声明监听事件

methods: {
    busEventTest(msg){
    alert('----------'+msg)
    }
}
mounted() {
    this.$bus.$on("event-bus", msg => {
    console.log('任意两个组件,补证组件接收到补牌组件发过来的消息----->',msg)
    })
    this.$bus.$on("event-bus", this.busEventTest)
}

调用监听事件

this.$bus.$emit('event-bus','测试eventBus')

Vue自带事件总线

创建myBus.js

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

main.js全局挂载

import myBus from './myBus'
Vue.prototype.$bus = myBus

声明监听事件

methods: {
    busEventTest(msg){
    alert('----------'+msg)
    }
}
mounted() {
    this.$bus.$on("event-bus", this.busEventTest)
}

调用监听事件

this.$bus.$emit('event-bus','测试eventBus')

事件重复触发,解决的办法就是调用监听事件后,需要手动进行销毁,那么是在哪个组件里进行销毁呢,测试结果是在调用监听事件的组件($emit所在的组件)里进行销毁

beforeDestroy () {
	this.$bus.$off("event-bus", this.busEventTest)
}

插槽

声明

myslot标识插槽slot自身的名字,唯一性,就像是自己的名字,别人通过名字可以找到你

:slotData标识插槽slot自身拥有的数据(属性、方法),别人通过名字找到你之后可以使用你的数据(属性、方法)

<slot name="myslot" :slotData="appointType"></slot>
<script>
    export default {
        data() {
                return {
                     appointType: false
             }	
        }
    }
</script>

使用

方式一

v-slot:myslot标识要使用哪个插槽slot

ctx任意命名的变量,通过该变量可以获取到前面声明的插槽slot的数据(属性、方法)

<template v-slot:myslot="ctx">
	来自子组件数据:{{ctx.slotData}}
</template>

方式二

slotData直接获取到前面声明插槽的数据,是方式一的一种简写形式

<template v-slot:myslot={slotData}>
	来自子组件数据:{{slotData}}
</template>

方式三

#myslot标识要使用哪个插槽slot,是方式一v-slot:myslot的一种简写形式

<template #myslot={slotData}>
	来自子组件数据:{{slotData}}
</template>

注意

前面插槽声明的数据是属性,声明的数据也可以是方法,个人更倾向直接声明一个对象,因为对象里面可以保护多个属性和方法

<slot name="myslot" :slotData="appointType" :slotMethod="handleParentClick"></slot>
<script>
export default {
	data() {
			return {
				 appointType: false
		 }	
	}
	methods: {
            handleParentClick(e) {
               console.info(e)
            }	
	}
}
</script>

使用插槽的时候需要注意,如果多次使用同一个插槽,只有最后一个才会生效

<template v-slot:myslot="ctx">
	来自子组件数据:{{ctx.slotData}}
</template>
<template v-slot:myslot={slotData}>
	来自子组件数据:{{slotData}}
</template>
<template #myslot={slotData}>
	来自子组件数据:{{slotData}}
</template>
<template #myslot={slotMethod}>
	来自子组件数据:{{slotMethod('aaaaa')}}
</template>
<template #myslot="ctx">
    来自子组件数据:{{ctx}}
    来自子组件数据:{{ctx.slotData}}
    来自子组件数据:{{ctx.slotMethod('aaabbb')}}
</template>
<template #myslot={slotData,slotMethod}>
    来自子组件数据:{{slotData}}
    来自子组件数据:{{slotMethod('aaabbb')}}
</template>

参考

Vue子父组件方法互调

Vue 插槽(slot)使用(通俗易懂)

Vue事件总线(EventBus)使用详细介绍