• Vue3【一】组件间的通信方式汇总



    父子组件通信是Vue中必不可少的一部分,在面试的时候也会问到,本篇文章中列举了7种组件间的通信方式,也算是一个总结。

    1. Props 方式(父传子)

    Props 方式是Vue中最常见的一种 父传子的方式,使用也比较简单。

    // 父组件
    <template>
    	<div>
    		<h1>父组件</h1>
    		<hr />
    		<Son :value='parentValue'></Son>
    	</div>
    </template>
    <script lang='ts'>
    import { defineComponent, ref } from 'vue'
    import son from './components/son.vue'
    
    export default defineComponent({
      components: { son },
      setup () {
        const parentValue = ref('父组件传给子组件的值')
        return {
        	parentValue
        }
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    子组件:由于Vue3中没有this,所以我们想要在setup中使用父组件传过来的值,需要使用setup函数的第一个参数,或者defineProps

    注意:当使用 setup 语法糖的时候,使用defineProps

    // 子组件
    <template>
      <div>
        <p>子组件</p>
        <div>{{ value }}</div>
      </div>
    </template>
    <script lang="ts">
    import { defineComponent } from 'vue'
     
    export default defineComponent({
      props: ['value'],
      setup (props, context) {
        console.log(props.value) // 父组件传给子组件的值
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2. emit(子传父)

    emit 方式也是组件常用的通信方式,用于子传父

    // 父组件
    <template>
      <div>
        <h1>父组件</h1>
        {{ parentValue }}
        <hr />
        <son @handle="handle"></son>
      </div>
    </template>
    <script lang="ts">
    import { defineComponent, ref } from 'vue'
    import son from './components/son.vue'
     
    export default defineComponent({
      components: { son },
      setup () {
        let parentValue = ref('父组件传给子组件的值')
        const handle = value => {
          parentValue.value = value
        }
        return {
        	parentValue, 
        	handle
        }
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    子组件通过emit触发父组件中的方法传值,需要使用setup函数的第二个参数,或者 defineEmits

    // 子组件
    <template>
      <div>
        <p>子组件</p>
        <button @click="handleClick">点击改变父组件的值</button>
      </div>
    </template>
    <script lang="ts">
    import { defineComponent, ref } from 'vue'
     
    export default defineComponent({
      setup (props, context) {
        const handleClick = () => {
          context.emit('handle', '子组件传给父组件的值')
        }
        return {
        	handleClick
        }
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    子组件点击按钮之后,emit 一个自定义事件,并将添加的值作为参数传递
    第一个参数:为 父组件中调用子组件中@后面的函数名
    第二个参数:为所传递的值

    父组件中只需监听子组件自定义的事件,然后执行对应的操作。

    3. expose / ref方式

    expose 与 ref 主要用于 父组件获取子组件的属性或方法。在子组件中,向外暴露出属性或方法,父组件便可以使用 ref 获取到子组件身上暴露的属性或方法

    // 子组件
    <script setup>
        // 方法一、使用expose对外暴露属性或方法
        ctx.expose({
            childName: "子组件的名称属性",
            childMethod(){
                console.log("子组件的方法");
            }
        })
        // 方法二,使用defineExpose
        //  defineExpose({
        //     childName: "子组件的名称属性",
        //     childMethod(){
        //         console.log("子组件的方法");
        //     }
        // })
    </script>
     
    // 父组件 
    <template>
        <child ref="childRef"></child>
        <button @click="handlerClick">按钮</button>
    </template>
    <script setup>
        import child from "./child.vue";
        import { ref } from "vue";
        const childRef = ref(null);
        const handlerClick = () => {
            // 获取子组件对外暴露的属性
            const childName = childRef.value.childName;
            console.log(childName);
            // 调用子组件对外暴露的方法
            comp.value.childMethod();
        }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    在这里解释下,可能会有些小伙伴们看不懂上面子组件中这些代码的写法。其实也很简单,方法一没有使用setup语法糖,方法二使用了setup语法糖,把setup放在了 script 标签里。ctx是setup函数的第二个参数;defineExpose是语法糖的写法,需要从vue中引入。

    4. attrs 方式

    attrs 主要用于子组件获取父组件中没有通过props接收的属性
    什么意思呢,看下面的代码

    // 父组件 传值
    <child :msg1="msg1" :msg2="msg2" title="子组件"></child>
    <script setup>
        import child from "./child.vue";
        import { ref, reactive } from "vue";
        const msg1 = ref("信息1");
        const msg2 = ref("信息2");
    </script>
     
    // 子组件 接收
    <script setup>
        // import { defineProps, useAttrs } from "vue";
        // 子组件接收msg1
        const props = defineProps({
            msg1: String
        })
        
        const attrs = useAttrs();
        // 因为子组件接收了msg1,所以打印的结果中不会包含msg1, { msg2:"信息1", title: "子组件" }
        // 如果子组件没有接收msg1,打印的结果就是 { msg1: "信息1", msg2:"信息12", title: "子组件" }
        console.log(attrs); 
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    5. provide / inject 方式

    provide / inject 方式是 Vue 中提供的一对API,无论层级多深,API都可以实现从父组件到子孙组件的数据传递
    provide 与 inject 主要为 父组件向子组件或孙组件或多级嵌套的子组件通信。
    .
    provide: 在父组件中可以通过 provide 提供需要向后代组件传递的信息
    inject:从父组件到该组件,无论嵌套多少层,都可以直接用 inject 拿到父组件传送的信息。

    // 父组件
    <script setup>
        import { provide } from "vue";
        // 父组件通过 provide 提供给子组件的信息
        provide("name", "提供给后代组件的信息");
    </script>
     
    // 子组件或后代组件(不管几级子组件)
    <script setup>
        import { inject } from "vue";
        // 后代组件通过 inject 可以直接拿到父组件提供的信息
        const name = inject("name");
        console.log(name); 
    </script>
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    6. 事件总线

    Vue 3 中移除了 eventBus,但可以借助第三方工具来完成。Vue 官方推荐使用 mitt 或 tiny-emitter

    mitt.js不是专门给 Vue 服务的,但 Vue 可以利用 mitt.js 做跨组件通信

    优点:

    • 足够小,仅有 200bytes
    • 支持全部事件的监听和批量删除
    • 不依赖 Vue 实例,可以夸框架使用,React 或者 Vue,甚至 jQuery 项目都能使用同一套库。
    npm install --save mitt
    
    • 1

    7. Vuex / Pinia 方式

    vuex相信小伙伴们对这个不会陌生,这里就不多介绍了。

    Pinia 是最近比较火热的一个工具,也是用来处理跨组件通信。

    结尾

    以上就是本篇文章的内容了,基本上把常用的组件通信方式给列举了出来,相对来说,是比较简单的,基本上都是 Vue3 的内容。

    当然,关于Vue组件间的通信方式,肯定不止这几种,比如Vue2如何进行通信在本文就没有列举出,Vue3 和 Vue2 的方式还是有一定差别的。

    至于为什么写这篇文章,有如下几点原因:

    1、想整体汇总下组件通信,最近一直在写 React,怕这些基础知识点自己给淡忘了。
    2、总结下面试题,以备不时之需。

    接下来应该还会更新Vue2、Vue3、React等等的相关面试题!

    如果这篇文章对你来说有点左右,能够帮你温故知新,欢迎点赞、评论、收藏,避免在需要的时候找不到。

    如果文章中有错误的地方,也欢迎大家斧正~

  • 相关阅读:
    stm32----用状态机判断单双击
    Pytorch Bert 中文分类 运行代码时候遇到的问题
    MySQL数据库操作(创建、修改、删除、查询)
    Python UI自动化 —— 关键字+excel表格数据驱动
    Java DbUtils实用
    不要小看 WebSocket!长连接、有状态、双向、全双工都是王炸技能
    Zookeeper3.7.1分布式安装部署
    基于Jeecgboot前后端分离的流程管理平台演示系统安装(五)
    实战案例:用 PySpark ML 构建流失预测模型
    is not allowed to connect to this mysql server
  • 原文地址:https://blog.csdn.net/qq_41131745/article/details/126186650