vue基础之组件通信(VUE3)

发布于:2025-06-27 ⋅ 阅读:(18) ⋅ 点赞:(0)


前言

vue3的组件通信和vue2相比在语法上会有些差距,且vue3有的通信方式也在功能上比vue2更加完善,比如provide/inject,vue3相比vue2多了支持响应式的功能。这里主要列出vue3的组件通信,且使用vue3的组合式API风格来实现。


提示:以下是本篇文章正文内容,下面案例可供参考

一、父子组件通信

1.父组件向子组件通信

(1)父组件传递:
只需要在引入的子组件标签上,传入(子组件那里已经定义的)参数名对应的值即可。
语法:
<template><子组件名称 :参数名1="值" :参数名2="值"></子组件名称></template>
(2)子组件接收:
使用props关键字。在vue2(选项式API)中,props直接定义在最外层和data、methods同级,而vue3的组合式api中则需要通过defineProps来定义,
即语法为:(语法糖形式)

const props = defineProps({ 参数名1: 参数类型, 参数名2: 参数类型 });

如果是setup()形式,则和setup()同级,写法和选项式api一致,一般写setup上面:

export default {
  props: {参数1: 参数值},
  setup(props) {
    // setup() 接收 props 作为第一个参数
    console.log(props.参数1)
  }
}

当然defineProps中不仅可以传对象也可以传字符串数组,一般是传递对象,因为需要定义参数类型。

使用时语法:props.参数名1

整体示例:
子组件:
ChildComponent.vue

<script setup>
import { ref } from 'vue';

const props = defineProps({
  title: {
    type: String,
    default: '默认标题',
  },
  btnFun: {
    type: Function,
    default: () => {},
  },
});
const inputValue = ref('');
</script>

<template>
  <div>
    <h2>{{ props.title }}</h2>
    <a-button type="primary" @click="props.btnFun">完成</a-button>
    <a-input v-model:value="inputValue" placeholder="请输入" />
  </div>
</template>

父组件:


<template>
  <child-component :title="测试标题" :btn-fun="() => { console.log('按钮被点击'); }">
  </child-component>
</template>

其中ChildComponent和btnFun可以是原值,也可以是“-”分割后的值,都可以识别。

2.子组件向父组件通信

使用emit,vue3定义emit,使用defineEmits,
子组件里:
定义语法:
const emit = defineEmits(['child-event1','child-event2']);
setup()形式定义位置同1中的defineProps。
触发语法:
emit('child-event1',要传递的参数)
父组件里:
接收语法:
<子组件名 @child-event1='本地定义函数名'/>
整体例子:

<!-- 父组件 -->
<template>
  <ChildComponent :message="parentMsg" @child-event="handleEvent" />
</template>

<script setup>
import { ref } from 'vue';
const parentMsg = ref('来自父组件的数据');

const handleEvent = (payload) => {
  console.log('子组件传来:', payload);
};
</script>

<!-- 子组件:ChildComponent -->
<template>
  <button @click="$emit('child-event', '触发事件')">发送数据</button>
</template>

<script setup>
const props = defineProps({
  message: String
});
const emit = defineEmits(['child-event']);
</script>

3.ref父组件直接操作子组件通信。

vue3中的语法,父组件:

<template>
	<子组件名称 ref="ref名称"/>
</template>

<script setup>
import { ref } from 'vue';
const 'ref名称' = ref(null); // 父组件可以通过'ref名称'拿到子组件上的方法和data等数据

</script>

示例:

<!-- 父组件 -->
<template>
  <ChildComponent ref="childRef" />
</template>

<script setup>
import { ref, onMounted } from 'vue';
const childRef = ref(null);

onMounted(() => {
  childRef.value.someMethod(); // 调用子组件方法
});
</script>

进阶:如果是遇到多个子组件按需加载的情况,则此时若要通过ref获取到子组件的信息,则子组件还需加上 defineExpose
场景:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

is里面循环的子组件(StepOne、StepTwo)里需要加上:在这里插入图片描述

二、跨代通信

1. 跨层级通信

使用provide/inject函数, 其中provide为后代组件提供数据,需要接收的后代组件则是通过inject去接收数据。
语法:
祖先组件发送数据:provide('注入名', 要传递的参数);
后代接收数据:inject('注入名',要接收的参数);
使用示例:

<!-- 祖先组件 -->
<script setup>
import { provide, ref } from 'vue';
const theme = ref('dark');
provide('theme', theme); // 提供数据
</script>

<!-- 深层子组件 -->
<script setup>
import { inject } from 'vue';
const theme = inject('theme'); // 注入数据
console.log(theme.value); // 'dark'
</script>

另:如果没有使用setup语法糖,provide(/inject)要在setup()函数内调用:

import { provide } from 'vue'

export default {
  setup() {
    provide(/* 注入名 */ 'message', /* 值 */ 'hello!')
  }
}

进阶:
provide第二个参数,即要传递的参数值可以是任意类型,包括响应式的状态,比如一个 ref;
provide可以传递多个,后代按照注入名字接收,如果有重复的则以离得最近的父代为准。

import { ref, provide } from 'vue'

const count = ref(0);
function updateCount() {
  count ++;
}
provide('key', { count, updateCount });

后代接收时:

<script setup>
import { inject } from 'vue'

const { count, updateCount } = inject('location'); 
</script>

<template>
  <button @click="updateCount">{{ count }}</button>
</template>

2.事件总线通信

使用mitt工具:
下载:npm install mitt
创建事件总线模块:
event-bus.js

import mitt from 'mitt';

const emitter = mitt();

export default emitter;

发送事件组件:
SenderComponent.vue

<template>
  <button @click="sendMessage">发送消息</button>
</template>

<script setup>
import emitter from './event-bus';

const sendMessage = () => {
  emitter.emit('custom-event', {
    message: '来自SenderComponent的消息',
    timestamp: new Date().toISOString()
  });
};
</script>

接收事件组件:
ReceiverComponent.vue

<template>
  <div>
    <p>接收到的消息: {{ receivedMessage }}</p>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import emitter from './event-bus';

const receivedMessage = ref('等待消息...');

const handleEvent = (payload) => {
  receivedMessage.value = payload.message;
  console.log('接收到事件:', payload);
};

onMounted(() => {
  // 注册事件监听
  emitter.on('custom-event', handleEvent);
});

onUnmounted(() => {
  // 移除事件监听,防止内存泄漏
  emitter.off('custom-event', handleEvent);
});
</script>

总结

以上用了大概五种方式来阐述组件之间的通信,这些在日常开发中比较常见,对于vue入门来说是需要去掌握并灵活运用的,对于子父组件一开始会有混乱不清的情况,这种在以后的练习和熟悉中会逐渐分清。


网站公告

今日签到

点亮在社区的每一天
去签到