- 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: