文章目录
1. 组件的通信
1.1. 父子组件之间的通信
1.1.1 父组件向子组件传值
方式一:父组件给子组件传值时,通过
v-on
绑定属性实现
// parent.vue
<template><div>
父子组件传值
<children:msg="msg":foo="foo"/></div></template><scriptsetuplang="ts">import{ ref }from'vue';import children from'./components/children.vue';let msg =ref('hello word');let foo =ref(10);</script><stylescoped></style>
子组件通过
defineProps
来接收接收父组件传递的值。
- 使用字符串的形式接收父组件传递的值
// children.vue
<template><divclass="wrapper">
这是子组件<br/>
父传子:{{ props.msg }} {{ props.foo }}
</div></template><scriptsetuplang="ts">let props =defineProps(['msg','foo'])</script><stylescoped></style>
- 使用对象的形式接收父组件传递的值
// children.vue
<template><divclass="wrapper">
这是子组件<br/>
父传子:{{ props.msg }} {{ props.foo }}
</div></template><scriptsetuplang="ts">let props =defineProps({msg: String,foo: Number
})</script><stylescoped></style>
- 使用对象的形式接收父组件传递的值(含默认值及必填参数设置)
// children.vue
<template><divclass="wrapper">
这是子组件<br/>
父传子:{{ props.msg }} {{ props.foo }}
</div></template><scriptsetuplang="ts">let props =defineProps({msg:{type: String,default:'',required:true// 设置后参数必传},foo:{type: Number,default:0}})</script><stylescoped></style>
- 结合 TypeScript 使用
// children.vue
<template><divclass="wrapper">
这是子组件<br/>
父传子:{{ props.msg }} {{ props.foo }}
</div></template><scriptsetuplang="ts">let props = defineProps<{
msg?: string;foo: number
}>()</script><stylescoped></style>
方式二:父组件通过
插槽(slot)
向子组件传递参数
- 子组件中通过
slot
标签传递参数 - 父组件中通过
template
插入内容,通过v-slot
可以接收插槽传递的数据
<!-- Parent.vue --><template><Child><template#default="{ message }">
{{ message }}
</template></Child></template><script>import Child from'./Child.vue'</script><!-- Child.vue --><template><div><slot:message="message"></slot></div></template><scriptsetuplang="ts">import{ ref }from'vue'const message =ref('Hello, world!')</script>
需要注意的是,插槽只能用于传递静态内容,如果需要传递动态内容,则需要使用props或者provide/inject来实现。此外,插槽还可以定义多个,并且可以通过name属性来区分不同的插槽。
方式三:
v-model
,子组件可直接修改父组件传递过来的值
在Vue3中,可以使用
v-model
指令来实现子组件直接修改父组件传递过来的值。具体来说,可以在父组件中使用
v-model
指令将一个变量与子组件的一个
prop
绑定起来,然后在子组件中使用
emit
方法触发一个名为
update:
加上prop名字的事件,并传递一个新的值作为参数。例如:
<!-- VmodelParent.vue --><template><div>
v-model传参:父组件
<VmodelChildv-model:isShow="isShow"/></div></template><scriptsetuplang="ts">import{ ref }from'vue';import VmodelChild from'./components/VmodelChild.vue';const isShow =ref(false)</script><stylescoped></style><!-- VmodelChild.vue --><template><div>
v-model传参:子组件
<button@click="handleClick">点击修改参数</button><br/>
{{ props.isShow }}
</div></template><scriptsetuplang="ts">import{ defineProps, defineEmits }from'vue';const props =defineProps({isShow:{type: Boolean,default:false}})const emit =defineEmits(["update:isShow"])consthandleClick=()=>{emit("update:isShow",!props.isShow)}</script><stylescoped></style>
1.1.2. 子组件向父组件传值
子组件向父组件传值,通过
defineEmits
实现
<template><divclass="wrapper">
这是子组件<br/><button@click="emitToParent">click</button></div></template><scriptsetuplang="ts">let emit =defineEmits(['event-to-parent'])letemitToParent=()=>{emit('event-to-parent','子组件传递给父组件的值')}</script><stylescoped></style>
1.2. 兄弟组件之间的通信
Vue 3 中移除了 eventBus,但可以借助第三方工具来完成。Vue 官方推荐使用
mitt
或
tiny-emitter
。
例子:以
mitt
为例
1.2.1. 安装
yarn add mitt -S
1.2.2. 注册
- eventBus.ts
// eventBus.tsimport mitt from'mitt'const mitter =mitt();exportdefault mitter
1.2.3. 使用
- EventBus.vue
// EventBus.vue
<template><div>
Event Bus实现兄弟组件传参
<EventBusA/><EventBusB/></div></template><scriptsetuplang="ts">import EventBusA from'./components/EventBusA.vue';import EventBusB from'./components/EventBusB.vue';</script><stylescoped></style>
- EventBusA.vue
// EventBusA.vue
<template><divclass="wrapper">
兄弟组件A
<buttontype="button"@click="handleClick">点击传参</button></div></template><scriptsetuplang="ts">import{ ref }from'vue';import mitter from'@/utils/eventBus'const msg =ref('Hello, world!')consthandleClick=()=>{
mitter.emit('msg', msg.value)}</script><stylescoped></style>
- EventBusB.vue
// EventBusB.vue
<template><divclass="wrapper">
兄弟组件B
{{ res }}
</div></template><scriptsetuplang="ts">import mitter from'@/utils/eventBus'import{ ref }from'vue'const res =ref()
mitter.on('msg',(data)=>{
res.value = data
})</script><stylescoped></style>
1.3. 跨级组件之间的通信
provide/inject来实现跨级组件之间的通信
1.3.1 provide/inject
- parent.vue
// parent.vue
<template><divclass="wrapper">
兄弟组件传参,这是父组件
<brotherA/><brotherB/></div></template><scriptsetuplang="ts">import brotherA from'./components/brotherA.vue'import brotherB from'./components/brotherB.vue'import{ provide, ref }from'vue';let msg =ref('给孙组件传递的值');provide('msg', msg)</script><stylescoped></style>
- brotherA.vue
// brotherA.vue
<template><divclass="wrapper">
子组件A
<grandson/></div></template><scriptsetuplang="ts">import grandson from"./grandson.vue";import{ ref }from'vue';</script><stylescoped></style>
- brotherB.vue
// brotherB.vue
<template><divclass="wrapper">
子组件B
{{ msg }}
</div></template><scriptsetuplang="ts">import{ inject }from'vue'let msg =inject('msg')</script><stylescoped></style>
- grandson.vue
// grandson.vue
<template><divclass="wrapper">
这是孙组件
{{ msg }}
</div></template><scriptsetuplang="ts">import{ inject }from'vue'let msg =inject('msg')</script><stylescoped></style>
1.4. 非父子组件之间的通信
1.4.1. Vuex/Pinia
Vuex 和 Pinia 是 Vue 3 中的状态管理工具,使用这两个工具可以轻松实现组件通信。由于这两个工具都比较强大,后面会写文章详细讲解。
总结
组件通信是 Vue 中非常重要的一个概念,它指的是组件之间传递数据和事件的过程。在 Vue 中,组件通信主要分为父子组件之间的通信和兄弟组件之间的通信两种情况。
在父子组件之间的通信中,父组件可以通过v-bind
来向子组件传递数据,而子组件则可以通过
defineProps
来接收父组件传递的数据。同时,子组件也可以通过
emit
触发自定义事件来向父组件传递数据。
在兄弟组件之间的通信中,可以通过一个共同的父组件来实现数据的传递和事件的触发,也可以通过 Vuex 等状态管理工具来实现数据的共享。
总之,在组件通信的过程中,需要合理地选择合适的方法来实现数据和事件的传递,以实现组件之间的良好协作和高效交互。
版权归原作者 剑九 六千里 所有, 如有侵权,请联系我们删除。