Communication of non-parent-child components

  • In development, after we build the component tree, in addition to the communication between parent and child components, there will also be communication between non-parent and child components.
  • Here we mainly talk about two methods:
    • Provide/Inject;
    • global event bus;

1. Provide and Inject

  • Provide/Inject is used to share data between non-parent-child components :
    • For example, there are some deeply nested components, and the child component wants to get part of the content of the parent component ;
    • In this case, if we still pass props down the component chain level by level, it will be very troublesome;
  • For this case we can use Provide and Inject :
    • No matter how deep the hierarchy is, a parent component can act as a dependency provider for all its child components ;
    • The parent component has a provide option to provide data;
    • Child components have an inject option to start using this data;
  • In fact, you can think of dependency injection as " long range props ", except:
    • The parent component does not need to know which child components use the properties it provides
    • Subcomponents don't need to know where the injected property comes from

1.1. Basic use of Provide and Inject 

We develop a structure like this:

1.2. How to write Provide and Inject functions 

  • If some data provided in Provide comes from data, then we may want to get it through this:
  • At this time, an error will be reported:
    • Here is a question for everyone to think about. Where does our this use?

1.3, processing responsive data 

  • Let's verify a result first: if we modify the content of this.names, will the subcomponents using length be responsive?
  • We will find that there is no response in the corresponding subcomponent :
    • This is because when we modify names , the this.names.length introduced in provide is not itself responsive;
  • So how can we make our data responsive?
    • Very simple, we can use some reactive APIs to complete these functions, such as computed functions ;
    • Of course, this computed is a new feature of vue3.
  • Note: We need to get the value when using length
    • This is because computed returns a ref object , and the value needs to be taken out for use

1.4. Examples 

HomeBanner.vue

<template>
  <div class="banner">
    <h2>HomeBanner: {
   
   { name }} - {
   
   { age }} - {
   
   {message.value}}</h2>
  </div>
</template>

<script>
  export default {
    inject: ["name", "age", "message"]
  }
</script>

<style scoped>
</style>

Home.vue

<template>
  <div class="home">
    <home-banner></home-banner>
  </div>
</template>

<script>
  import HomeBanner from './HomeBanner.vue'

  export default {
    components: {
      HomeBanner
    }
  }
</script>

<style scoped>
</style>

app.vue

<template>
  <div class="app">
    <home></home>
    <h2>App: {
   
   { message }}</h2>
    <button @click="message = 'hello world'">修改message</button>
  </div>
</template>

<script>
  import { computed } from 'vue'
  import Home from './Home.vue'

  export default {
    components: {
      Home
    },
    created() {

    },
    data() {
      return {
        message: "Hello App"
      }
    },
    // provide一般都是写成函数
    provide() {
      return {
        name: "why",
        age: 18,
        // message:this.message, // 这种方式绑定的message数据,是data中固定的数据,当我们修改message后,这个值也是固定不变的,不能获取到最新数据。
        message: computed(() => this.message)  // 使用这种方式,能够响应式的获取到message的最新值。这里使用箭头函数,因为箭头函数不绑定this,所以我们能通过this.message方式获取值
      }
    }
  }
</script>

<style scoped>
</style>

2. Global event bus

Vue3 removed the $on, $off and $once methods from the instance, so if we want to continue to use the global event bus, we need to use a third-party library:

  • Vue3 officially recommends some libraries, such as mitt or tiny-emitter ;
  • Here we mainly explain the use of hy-event-store;

First, we need to install this library first:

npm install hy-event-bus

Second, we can encapsulate a tool eventbus.js:

They can be used in projects:

  • We listen to events in App.vue;
  • We trigger events in Banner.vue;

In some cases we may want to cancel the function listener registered before: 

Guess you like

Origin blog.csdn.net/weixin_52851967/article/details/128740719