VUE3-组件通信

VUE3-组件通信

props

props是使用频率最高的一种通信方式,对于父传子而言,这种方式很方便

使用props实现子传父,就现在父定义方法,将方法给子,然后子在合适的时机调用此方法将数据传给父

相当于子不直接把内容给父,而是父先给子一个盒子,子把东西装在盒子里扔给父


自定义事件

事件名为多个单词组成的情况下,推荐事件使用肉串(kebab-case)命名,函数使用驼峰命名

在父组件给子组件元素绑定一个自定义事件,并定义一个事件的回调函数

<template>
	<child @send-msg="save"/ >
    

</template>
<script setup>
	import child from 'child.vue'
    
    function save(value){
        // 事件的回调方法,参数value可以由子组件传递,在这里接收
    }
</script>

在子组件使用defineEmits的方法接受此事件,并且在合适的时机触发事件

const emit = defineEmits(['send-msg'])

emit('send-msg') // 触发此事件

尽管直接通过 props 传递回调函数也能实现子组件向父组件传递消息,但使用事件系统具有更好的实践意义,它能带来更清晰的代码结构、更高的可维护性和更好的职责分离,这些都是构建大型应用所必需的。因此,推荐使用自定义事件的方式来实现子组件向父组件的消息传递


mitt

mitt 是一个轻量级的事件发射器(event emitter)库,它允许你创建一个简单的事件总线(event bus),以便在你的应用中不同组件或模块之间传递消息

developit/mitt: 🥊 Tiny 200 byte functional event emitter / pubsub.

# 安装工具
npm i mitt
import mitt from 'mitt'

const emitter = mitt()

export default emitter

常用API:

  • on:绑定事件
  • off:解绑事件
  • all.clear:解绑所有事件
  • emit:触发事件,参数为事件名称
// 使用生命周期钩子定义emitter的事件解绑,有利于资源释放
onUnmouted(()=>{
    emitter.off('send-toy')
})

v-model

当v-model用于html标签上时,可以实现元素与数据之间的双向绑定,其底层原理是使用响应式数据+input事件触发的原理

<input type='text' v-model='username'>
<!-- 底层原理 -->
<input type='text' @input='username = (<HTMLInputElement>$event.target).value'>

在实际开发中,我们经常使用组件库中的组件来代替类似于input的表单元素,实现精美的效果

但是一个普通的组件是无法使用v-model与数据进行双向绑定的

这里,底层使用的还是props与自定义事件来配合完成组件之间的通信

在使用时,我们也无需手动的props和自定义事件来实现数据的双向绑定,而是使用v-model直接语法糖使用

这样就完成了UI组件和调用组件之间的双向通信


$attrs

这是一个vue对象中的属性,当父通过props的方式传参给子组件的时候,子组件没有使用defineProps显式接受的参数都会存在这个$attrs属性中

子组件可以通过将这个属性再次传递的方式将这组没被自己接受的参数再次传给子组件

这个属性在二次封装UI组件的时候很有用,不想写一堆属性的时候就可以写成: v-bind="$attrs"

<child v-bind="{a:a,b:b}">
// v-bind对象,可以批量传输props
<child :a="a" :b="b">

ref&parent

这个特性我们用过,可以在父子组件中暴露数据让对方操作

使用defineExpose函数暴露,其参数是一个对象

我们可以使用ref操作子组件中暴露的内容

也可以使用parent操作父组件中暴露的内容


provide

从vue对象中获取provide属性,这个属性可以向自己的所有后代提供数据

从vue对象中获取inject属性,这个属性可以注入已经提供的数据

这个数据如果是响应式数据,那么后代获取的也是响应式数据,即在后代中修改数据,其父组件的值也会被修改


slot

默认插槽:组件也可以写成双标签的形式,vue会将组件起始标签和结束标签中的其他元素标签内容放到被slot标签占位的位置

具名插槽:子组件的slot元素标签使用name属性标识后,在父组件中的组件标签上加入v-slot=[name属性值]的方式,把指定内容插入指定插槽中

在这里,可以在元素上包裹一层template标签,将v-slot属性直接加在template标签中

在这里,v-slot=可以被简写成# ,很多UI组件库都将这里的属性简写成#

作用域插槽:UI组件库中会大量使用作用域插槽,一些弹窗,表格都是通过默认与插槽来实现的