目录
父子组件通信是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等等的相关面试题!
如果这篇文章对你来说有点左右,能够帮你温故知新,欢迎点赞、评论、收藏,避免在需要的时候找不到。
如果文章中有错误的地方,也欢迎大家斧正~