浅学一下 --- Vue 组件通信

37 阅读2分钟

props / emits

  • props只能是父组件向子组件进行传值,props使得父子组件之间形成了一个单向下行绑定,子组件的数据会随着父组件不断更新。
  • props 可以显示定义一个或一个以上的数据。
  • props属性名规则:若在props中使用驼峰形式,模板中需要使用短横线的形式

子组件

<script setup>
defineProps({
  message: {
    type: String,
  },
});
const emits = defineEmits(["update"]);

const sendMessageToParent = () => {
  emits("update", "Hello from child");
};
</script>

<template>
  <button @click="sendMessageToParent">{{ message }}</button>
</template>

父组件

<script setup>
import { ref } from "vue";
import HelloWorld from "./components/HelloWorld.vue";

const parentMessage = ref("Hello from parent");

const updateMessage = (newMessage) => {
  parentMessage.value = newMessage;
};
</script>

<template>
  <HelloWorld :message="parentMessage" @update="updateMessage" />
</template>

project / inject

有一些多层级嵌套的组件,形成了一颗巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅使用 props 则必须将其沿着组件链逐级传递下去,这会非常麻烦。

image.png

  • project 钩子用来发送数据或方法
  • inject钩子用来接收数据或方法

祖先组件:

<script setup>
import { ref, provide } from "vue";
import HelloWorld from "./components/HelloWorld.vue";

const parentMessage = ref("Hello from parent");

provide('message', parentMessage);
</script>

<template>
 <HelloWorld />
</template>

父组件:

<script setup>
import TheWelcome from './TheWelcome.vue';
</script>

<template>
 <TheWelcome />
</template>

子组件:

<script setup>
import { inject } from 'vue';
const message = inject('message');
</script>

<template>
 <button>{{ message }}</button>
</template>

eventBus事件总线

eventBus事件总线适用于父子组件非父子组件等之间的通信

创建事件中心管理组件之间的通信

// EventBus.js
import { ref } from 'vue';

const eventBus = ref(new Vue());

export default eventBus;

SiblingComponent1.vue

<script setup>
import eventBus from "./EventBus.js";

const sendDataToSibling = () => {
 eventBus.value.$emit("custom-event""Data from Sibling 1");
};
</script>

<template>
 <button @click="sendDataToSibling">Send Data to Sibling 2</button>
</template>

SiblingComponent2.vue

<script>
import eventBus from './EventBus.js';

export default {
 data() {
   return {
     receivedData'',
  };
},
 created() {
   // 监听来自事件总线的自定义事件
   eventBus.value.$on('custom-event', (data) => {
     this.receivedData = data;
  });
},
};
</script>

<template>
 <div>Received Data: {{ receivedData }}</div>
</template>

$attrs / $listeners

$attrs$listeners 是用于访问父组件传递的属性和监听器的特殊属性。通常用于处理传递给子组件的未明确声明的属性和事件。

$attrs:

$attrs 包含了父组件传递给子组件但子组件没有声明的属性。这对于将属性传递到子组件的根元素或其他子元素非常有用。

<!-- ParentComponent.vue -->
<template>
 <ChildComponent custom-attr="Custom Attribute" />
</template>
<!-- ChildComponent.vue -->
<template>
 <p>{{ $attrs.custom-attr }}</p>
</template>

在上面的示例中,custom-attr 属性被传递给了子组件,但子组件没有明确声明它。子组件可以通过 $attrs 访问这个属性。

$listeners:

$listeners 包含了父组件传递给子组件的事件监听器。

<!-- ParentComponent.vue -->
<template>
 <ChildComponent @custom-event="handleEvent" />
</template>
<!-- ChildComponent.vue -->
<template>
 <button @click="$listeners['custom-event']('Data from Child')">Trigger Event</button>
</template>

在上面的示例中,custom-event 事件监听器被传递给了子组件,子组件可以通过 $listeners 来触发该事件。