Vue3.0组合式API系列文章:
《Vue3.0组合式API:setup()函数》
《Vue3.0组合式API:使用reactive()、ref()创建响应式代理对象》
《Vue3.0组合式API:computed计算属性、watch监听器、watchEffect高级监听器》
《Vue3.0组合式API:使用defineProps()实现父组件向子组件传递数据》
《Vue3.0组合式API:使用defineEmits()实现子组件向父组件传递数据》
《Vue3.0组合式API:生命周期钩子函数》
《Vue3.0组合式API:依赖注入provide和inject实现跨层组件的通信》
《Vue3.0组合式API:使用ref获取DOM元素》
1、Prop 逐级透传问题
通常情况下,当我们需要从父组件向子组件传递数据时,会使用 props。想象一下这样的结构:有一些多层级嵌套的组件,形成了一棵巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅使用 props 则必须将其沿着组件链逐级传递下去,这会非常麻烦:
注意,虽然这里的 <Footer> 组件可能根本不关心这些 props,但为了使 <DeepChild> 能访问到它们,仍然需要定义并向下传递。如果组件链路非常长,可能会影响到更多这条路上的组件。这一问题被称为“prop 逐级透传”,显然是我们希望尽量避免的情况。
2、provide 和 inject 的使用
provide 和 inject 可以帮助我们解决这一问题。一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。
provide() 函数:为组件后代提供数据。
inject() 函数:要注入上层组件提供的数据。
语法格式:
<script setup>//第一步:导入函数
import { provide, inject } from 'vue';//第二步:使用provide函数,传递数据
provide('key', '数据');//第三步:使用inject函数,接收数据
const data = inject('key');</script>
2.1 跨层组件的数据传递与接收
【实例】使用依赖注入 provide 和 inject 函数,实现跨层级组件之间数据的传递与接收。
(1)修改 App.vue 根组件文件,实现爷爷组件功能,并使用 provide 传递数据。
<template><fieldset><legend>爷爷组件</legend><!-- 使用组件 --><ParentComponent></ParentComponent></fieldset>
</template><!-- 使用 <script setup> 语法糖 -->
<script setup>//导入组件,使用 <script setup> 语法糖,导入的组件将会自动执行注册
import ParentComponent from '@/components/ParentComponent.vue';import { reactive, provide } from 'vue';// 使用 reactive 创建响应式的对象
const blogInfo = reactive({blogName: '您好,欢迎访问 pan_junbiao的博客',blogUrl: 'https://blog.csdn.net/pan_junbiao'
});//核心代码:使用provide函数,传递数据
provide('blogName-key', blogInfo.blogName);
provide('blogUrl-key', blogInfo.blogUrl);</script>
(2)创建 ParentComponent.vue 父组件。
<template><fieldset><legend>父组件</legend><!-- 使用组件 --><ChildComponent></ChildComponent></fieldset>
</template><!-- 使用 <script setup> 语法糖 -->
<script setup>//导入组件,使用 <script setup> 语法糖,导入的组件将会自动执行注册
import ChildComponent from '@/components/ChildComponent.vue'</script>
(3)创建 ChildComponent.vue 子组件,并使用 inject 接收爷爷组件传递的数据。
<template><fieldset><legend>子组件</legend><h3>子组件接收到爷爷组件传递的数据:</h3><p>博客信息:{{ blogName }}</p><p>博客信息:{{ blogUrl }}</p></fieldset>
</template><!-- 使用 <script setup> 语法糖 -->
<script setup>
import { ref , inject} from 'vue';// 使用 ref 创建响应式的对象
const blogName = ref('');
const blogUrl = ref('');// 核心代码:使用inject函数,接收数据
blogName.value = inject('blogName-key');
blogUrl.value = inject('blogUrl-key');</script>
执行结果:
2.3 跨层组件的数据修改
provide 和 inject 函数可以传递和接收数据,同时也可以传递和接收一个方法。通过传递与接收一个方法,可以实现跨层组件的数据修改。
【实例】使用依赖注入 provide 和 inject 函数,实现跨层级组件之间数据的修改。
(1)修改 App.vue 根组件文件,实现爷爷组件功能,并使用 provide 传递数据。
<template><fieldset><legend>爷爷组件</legend><p>计数结果:{{ count }}</p><!-- 使用组件 --><ParentComponent></ParentComponent></fieldset>
</template><!-- 使用 <script setup> 语法糖 -->
<script setup>//导入组件,使用 <script setup> 语法糖,导入的组件将会自动执行注册
import ParentComponent from '@/components/ParentComponent.vue';import { ref, provide } from 'vue';// 使用 ref 创建响应式的对象
const count = ref(0);//定义一个方法:计数功能
const setCountFun = () => {count.value++;
}//核心代码:使用provide函数,传递一个方法
provide('setCountFun-key', setCountFun);</script>
(2)创建 ParentComponent.vue 父组件。
<template><fieldset><legend>父组件</legend><!-- 使用组件 --><ChildComponent></ChildComponent></fieldset>
</template><!-- 使用 <script setup> 语法糖 -->
<script setup>//导入组件,使用 <script setup> 语法糖,导入的组件将会自动执行注册
import ChildComponent from '@/components/ChildComponent.vue'</script>
(3)创建 ChildComponent.vue 子组件,并使用 inject 接收爷爷组件传递的一个方法。
<template><fieldset><legend>子组件</legend><h3>子组件接收到爷爷组件传递的一个方法:</h3><button @click="setCountFun">修改爷爷组件的数据</button></fieldset>
</template><!-- 使用 <script setup> 语法糖 -->
<script setup>
import { inject } from 'vue';// 核心代码:使用inject函数,接收一个方法
const setCountFun = inject('setCountFun-key');</script>
执行结果: