Vue 3 Chapter Eleven: Component Two (Component Communication)

1. Communication of components

1.1. Communication between parent and child components

1.1.1 Pass value from parent component to child component

Method 1: When the parent component passes a value to the child component, v-onit is realized by binding properties

// parent.vue
<template>
  <div>
    父子组件传值
    <children :msg="msg" :foo="foo"/>
  </div>
</template>

<script setup lang="ts">
import {
      
       ref } from 'vue';
import children from './components/children.vue';

let msg = ref('hello word');
let foo = ref(10);
</script>

<style scoped>

</style>

The child component definePropsreceives the value passed by the parent component.

  • Receive the value passed by the parent component in the form of a string
// children.vue
<template>
  <div class="wrapper">
    这是子组件<br/>
    父传子:{
   
   { props.msg }} {
   
   { props.foo }}
  </div>
</template>

<script setup lang="ts">
let props = defineProps(['msg', 'foo'])
</script>

<style scoped>

</style>
  • Use the form of an object to receive the value passed by the parent component
// children.vue
<template>
  <div class="wrapper">
    这是子组件<br/>
    父传子:{
   
   { props.msg }} {
   
   { props.foo }}
  </div>
</template>

<script setup lang="ts">
let props = defineProps({
      
      
  msg: String,
  foo: Number
})
</script>

<style scoped>

</style>
  • Receive the value passed by the parent component in the form of an object (including default values ​​and required parameter settings)
// children.vue
<template>
  <div class="wrapper">
    这是子组件<br/>
    父传子:{
   
   { props.msg }} {
   
   { props.foo }}
  </div>
</template>

<script setup lang="ts">
let props = defineProps({
      
      
  msg: {
      
      
    type: String,
    default: '',
    required: true // 设置后参数必传
  },
  foo: {
      
      
    type: Number,
    default: 0
  }
})
</script>

<style scoped>

</style>
  • Use with TypeScript
// children.vue
<template>
  <div class="wrapper">
    这是子组件<br/>
    父传子:{
   
   { props.msg }} {
   
   { props.foo }}
  </div>
</template>

<script setup lang="ts">
let props = defineProps<{
      
      
  msg?: string;
  foo: number
}>()
</script>

<style scoped>

</style>

Method 2: The parent component 插槽(slot)passes parameters to the child component

  • slotPass parameters through tags in subcomponents
  • Insert the content in the parent component templateand v-slotreceive the data passed by the 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>

<script setup lang="ts">
import {
      
       ref } from 'vue'
const message = ref('Hello, world!')
</script>

It should be noted that slots can only be used to pass static content. If you need to pass dynamic content, you need to use props or provide/inject to achieve it. In addition, multiple slots can be defined, and different slots can be distinguished through the name attribute.

Method 3: v-model, the child component can directly modify the value passed by the parent component

In Vue3, v-modelinstructions can be used to implement child components to directly modify the value passed by the parent component. Specifically, you can use instructions in the parent component to bind v-modela variable to one of the child components , and then use a method in the child component to trigger an event named plus the name of the prop, and pass a new value as a parameter. For example:propemitupdate:

<!-- VmodelParent.vue -->
<template>
  <div>
    v-model传参:父组件
    <VmodelChild v-model:isShow="isShow" />
  </div>
</template>

<script setup lang="ts">
import {
      
       ref } from 'vue';
import VmodelChild from './components/VmodelChild.vue';

const isShow = ref(false)

</script>

<style scoped>

</style>



<!-- VmodelChild.vue -->
<template>
  <div>
    v-model传参:子组件
    <button @click="handleClick">点击修改参数</button>
    <br />
    {
   
   { props.isShow }}
  </div>
</template>

<script setup lang="ts">
import {
      
       defineProps, defineEmits } from 'vue';

const props = defineProps({
      
      
  isShow: {
      
      
    type: Boolean,
    default: false
  }
})
const emit = defineEmits(["update:isShow"])
const handleClick = () => {
      
      
  emit("update:isShow", !props.isShow)
}

</script>

<style scoped>

</style>

1.1.2. Child components pass values ​​to parent components

The child component passes the value to the parent component by defineEmitsimplementing

<template>
  <div class="wrapper">
    这是子组件<br/>
    <button @click="emitToParent">click</button>
  </div>
</template>

<script setup lang="ts">
let emit = defineEmits(['event-to-parent'])
let emitToParent = () => {
      
      
  emit('event-to-parent', '子组件传递给父组件的值')
}

</script>

<style scoped>

</style>

1.2. Communication between sibling components

The eventBus was removed in Vue 3, but it can be done with the help of third-party tools. Vue officially recommends using mittor tiny-emitter.

Example: Take mittas an example

1.2.1. Installation

yarn add mitt -S

1.2.2. Registration

  • eventBus.ts
// eventBus.ts
import mitt from 'mitt'

const mitter = mitt();

export default mitter

1.2.3. Use

  • EventBus.vue
// EventBus.vue
<template>
  <div>
    Event Bus实现兄弟组件传参
    <EventBusA />
    <EventBusB />
  </div>
</template>

<script setup lang="ts">
import EventBusA from './components/EventBusA.vue';
import EventBusB from './components/EventBusB.vue';
</script>

<style scoped>

</style>
  • EventBusA.vue
// EventBusA.vue
<template>
  <div class="wrapper">
    兄弟组件A
    <button type="button" @click="handleClick">点击传参</button>
  </div>
</template>

<script setup lang="ts">
import {
      
       ref } from 'vue';
import mitter from '@/utils/eventBus'

const msg = ref('Hello, world!')

const handleClick = () => {
      
      
  mitter.emit('msg', msg.value)
}

</script>

<style scoped>

</style>
  • EventBusB.vue
// EventBusB.vue
<template>
  <div class="wrapper">
    兄弟组件B
    {
   
   { res }}
  </div>
</template>

<script setup lang="ts">
import mitter from '@/utils/eventBus'
import {
      
       ref } from 'vue'

const res = ref()

mitter.on('msg', (data) => {
      
      
  res.value = data
})
</script>

<style scoped>

</style>

1.3. Communication between cross-level components

Provide/inject to realize communication between cross-level components

1.3.1 provide/inject

  • parent.view
// parent.vue
<template>
  <div class="wrapper">
    兄弟组件传参,这是父组件
    <brotherA />
    <brotherB />
  </div>
</template>

<script setup lang="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>

<style scoped>

</style>
  • brotherA.vue
// brotherA.vue
<template>
  <div class="wrapper">
    子组件A
    <grandson />
  </div>
</template>

<script setup lang="ts">
import grandson from "./grandson.vue";
import {
      
       ref } from 'vue';


</script>

<style scoped>

</style>
  • brotherB.vue
// brotherB.vue
<template>
  <div class="wrapper">
    子组件B
    {
   
   { msg }}
  </div>
</template>

<script setup lang="ts">
import {
      
       inject } from 'vue'

let msg = inject('msg')
</script>

<style scoped>

</style>
  • grandson.vue
// grandson.vue
<template>
  <div class="wrapper">
    这是孙组件
    {
   
   { msg }}
  </div>
</template>

<script setup lang="ts">
import {
      
       inject } from 'vue'

let msg = inject('msg')
</script>

<style scoped>

</style>

1.4. Communication between non-parent-child components

1.4.1. Vuex/Pinia

Vuex and Pinia are the state management tools in Vue 3, using these two tools can easily achieve component communication. Since these two tools are relatively powerful, I will write an article to explain them in detail later.

Summarize

Component communication is a very important concept in Vue, which refers to the process of passing data and events between components. In Vue, component communication is mainly divided into communication between parent and child components and communication between sibling components.
In the communication between parent and child components, the parent component can v-bindpass data to the child component through , and the child component can definePropsreceive the data passed by the parent component through . At the same time, child components can also emitpass data to parent components by triggering custom events.
In the communication between sibling components, data transfer and event triggering can be realized through a common parent component, and data sharing can also be realized through state management tools such as Vuex.
In short, in the process of component communication, it is necessary to choose an appropriate method to realize the transfer of data and events, so as to achieve good cooperation and efficient interaction between components.

Guess you like

Origin blog.csdn.net/to_the_Future/article/details/129542576