【Vue3实践】(四)优雅使用VUE3 组件特性:属性透传、依赖注入、组件插槽、动态组件

文章目录

  • 1.前言
  • 2.属性透传
  • 3.依赖注入
  • 4.组件插槽(slot)
    • 4.1.使用默认插槽
    • 4.2.使用具名插槽
    • 4.3.Element Plus中的dialog例子
  • 5.动态组件
  • 6.总结

1.前言

由于在日常开发中会有一部分前端的开发任务,会涉及到Vue的项目的搭建、迭代、构建发布等操作,所以想系统的学习一下Vue相关的知识点,本专题会依照Vue的搭建、开发基础实践、进阶用法、打包部署的顺序进行记录。

历史文章链接如下:

《Vue3搭建、路由配置与基本语法》
《响应式变量、双向绑定、计算属性、监听器》
《优雅使用VUE3 组件特性:组件定义、组件注册、事件监听、双向绑定》
《优雅使用VUE3 组件特性:属性透传、依赖注入、组件插槽、动态组件》
《组合式函数、环境变量、axios配置》
《打包部署、nginx配置、Docker镜像构建》

本篇是VUE3组件的第二部分,主要包括以下内容:

  • 属性透传的作用和使用方式,与propsemits的区别
  • 依赖注入的作用和使用方式,与透传的区别
  • 如何使用组件插槽
  • 动态组件的使用

2.属性透传

有时候我们可能需要在组件中将一些 props 或者事件透传给其子组件或者父组件。透传的目的是为了让子组件直接访问父组件的属性或者方法,或者父组件能够直接访问子组件的属性或者方法,这种父子组件之间传递属性的方式就是透传,透传可以避免在中间层组件中重复定义这些属性或者方法,提高代码的可维护性和复用性。

在上一篇博客中聊到了可以用propsemits 来建立父子组件之间进行通信,其中,props 是父组件向子组件传递数据的方式,而 emits 则是子组件向父组件触发事件的方式,通过这两种方式交换数据其实也是一种特殊的透传方式。

严格意义上的透传,不需要使用propsemits来定义变量,这种透传形式常见于:classstyle事件监听器等。

以事件监听为例,在上一篇中提到过一个例子,有一个计数器的组件,每点击一次可以让父组件中的计数值+1,我们是通过defineEmits完成的子组件对父组件的调用。

通过事件的透传,可以直接在父组件上定义点击事件让子组件触发,代码如下:

  • 父组件:
    <template>
      <div class="hello">
        <Count @click="doIncr" />
        <Count @click="doIncr" />
    
        <div>父组件的计数:{{ count }}div>
      div>
    template>
    
    <script setup>
    import Count from "../components/Count.vue";
    import { ref } from "vue";
    
    const count = ref(0);
    
    const doIncr = () => {
      count.value++;
    };
    script>
    
  • 子组件:
    <template>
      <div>
        <button>点击 + 1button>
      div>
    template>
    
    <script setup>
    
    script>
    

从上面的代码可以看到,子组件里面几乎什么都没有做,就可以直接使用父组件的点击事件了,代码更加简洁。

3.依赖注入

依赖注入就是可以在组件树的任一一个组件节点中提供一些需要传递的属性,在这个节点的任一子节点中都可以将这些属性注入使用,例如在下面这个组件树中,我想在最上面的Parent节点中提供一些属性,在最下面的child中使用就可以使用依赖注入的方式。
【Vue3实践】(四)优雅使用VUE3 组件特性:属性透传、依赖注入、组件插槽、动态组件_第1张图片

有了透传为什么还需要依赖注入呢?
透传的方式是需要在组件树中一级一级的向下传递,中间节点其实并不关系这个需要传递的属性,这样就消耗了额外的性能。
其次,在传递的过程中如果被中间的某个节点通过定义props消费掉,那这个消费的节点也需要按照再次通过props传递到子节点中,才能继续往下传递。

这时候就突出了依赖注入的价值,我只需要在parent中通过provide函数定义需要传递的属性,然后在需要使用的组件节点中使用inject注入属性即可。

  • 父组件:提供一个对象
    <template>
      <div class="hello">
        <InjectChild />
      div>
    template>
    
    <script setup>
    import { provide } from "vue";
    import InjectChild from "../components/InjectChild.vue";
    
    provide("injectData", { id: 1, name: "挥之以墨" });
    script>
    
  • 子组件:在视图中显示注入的对象
    <template>
      <div>
        注入的属性为:{{ data }}
      div>
    template>
    
    <script setup>
    import { inject } from "vue";
    
    const data = inject("injectData");
    script>
    

【Vue3实践】(四)优雅使用VUE3 组件特性:属性透传、依赖注入、组件插槽、动态组件_第2张图片

4.组件插槽(slot)

在之前的例子中,父组件引入子组件都是完整的引用了子组件的整个