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>

子组件:由于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>

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>

子组件通过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>

子组件点击按钮之后,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>

在这里解释下,可能会有些小伙伴们看不懂上面子组件中这些代码的写法。其实也很简单,方法一没有使用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>

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>
 

6. 事件总线

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

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

优点:

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

7. Vuex / Pinia 方式

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

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

结尾

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

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

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

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

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

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

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

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值