一定要会的Vue3组件通信方式

342 阅读2分钟

大家好,我是风柳老,一名菜鸡前端。

前言

本篇文章主要讲述vue3使用的组件通信方式,使用的是setup这种组合式的写法。

本篇文章将介绍以下种组件通信方式。

  • props
  • emit
  • v-model
  • ref/$parent
  • useAttrs
  • provide/inject
  • pinia
  • slot
  • mitt

props

props是最常见的一种父传子的通信方式。

父组件通过v-bind绑定自定义属性传输数据

//父组件示例
<child :dialogData="dialogData" />

子组件通过defineProps获取父组件传来的值

// 接受父组件传递过来的值
const props = defineProps({
  dialogData: {
    type: Object,
    default: () => ({
      isVisible: false,
    }),
  },
})

emit

emit也是最常见的一种子传父的通信方式。

父组件通过v-on绑定自定义事件来获取数据

//父组件示例
 <child  @hideBtnClick="hideBtnClick"/>
  <script setup>
    const hideBtnClick = (val) => {
      console.log(val)
   }
  </script>

子组件通过defineEmits来传输数据。小括号里数组可绑定多个事件传输多个数据

// 子传父 绑定事件
const emits = defineEmits(['hideBtnClick'])
//向父组件传输数据
 emits('hideBtnClick', '稀土掘金')

v-model

v-model写在组件上可实现父子组件中的通信

//父组件示例
<child v-model='car' />
       <!-- 
       v-model组件上使用
       一:相当有给子组件传递props[modelValue] = car
       二:相当于给子组件绑定自定义事件update:modelValue
       -->

v-model 还可以支持多个数据的双向绑定。

<child1 v-model:one="one" v-model:two="two" />

useAttrs

props类似获取到父组件的数据

propsuseAttrs()对比:props优先级更高;如果props拿到值,useAttrs()就拿不到; 但useAttrs()可以拿到父组件的事件

let $attrs=useAttrs()  //此方法会返回一个对象,父组件传的所有属性/事件与值

ref/$parent

ref

ref可以获取真实的DOM节点,可以获取到子组件示例VC

//父组件示例
<child ref='child' />
<script setup>
    //定义的变量名一定要与ref属性值相同
    const child = ref(null)
</script>

子组件内部数据对外关闭的,别人不能访问

如果想让外部访问需要通过defineExpose方法对外暴露。

const money=ref(600)
const fly=()=>{
    console.log("fly")
}
//子组件暴露
defineExpose{        
    money,
    fly
}

$parents

$parent可以在子组件内部获取到父组件实例

//子组件拿到
<button @click=handler($parent)></button>
<script setup>
   const handler=($parent)=>{
    console.log($parent)
}
</script>

父组件暴露子组件所需的数据

//父组件暴露money
defineExpose{
    money
}

provide与inject(响应式修改)

用来实现隔辈组件传递数据

provide

爷爷组件给孙子组件提供数据;两个参数:第一个参数就是提供的数据key,第二个参数即祖先组件提供的数据

provide('key',value)

inject

注入祖先组件提供的数据;需要一个参数:祖先组件提供数据的key

let val=inject('key')

pinia

pinia官方文档

pinia同样是一个Vue状态管理工具,它和vuex有很多相似的地方。本质上他是vuex团队核心成员开发的,在vuex上面提出了一些改进。与vuex相比,pinia去除了vuex中对于同步函数Mutations和异步函数Actions的区分。直接在Actions中便能够使用同步和异步方法(在vuex的开发计划中也将会除去同步和异步的区分)。其次相比于vuexpinia对于typescript的支持性更好,友好的devTools支持,pinia只有1kb,简化了很多方法的写法。由于vuex比较完善,因此,pinia更加适合小型项目,vuex更加适合大型项目。

定义pinia

let useTodoStore=defineStore("todo",()=>{
    let todos=ref([{id:1,title:'吃饭'},{id:2,title:'睡觉'},{id:3,title:'喝水'}])
    let arr=ref([])
    //计算:getter
    let total=computed(()=>{
        return  arr.value.reduce(pre,next=>pre+next,0)
    })
    //务必要返回一个对象:属性和方法可以提供给组件使用
    return {
        todos,
        arr,
        total,
        updateTodo(){
            todos.value.push({id:4title:'写代码'})
        }
    }
})

在组件中使用

//组件中引入pinia
import useTodoStore from '@/stores/modules/
// 使用useTodoStore数据
const todoStore = useTodoStore()

slot

主要讲解作用域插槽实现组件通信

作用域插槽:可以传递数据的插槽,子组件可以将数据回传给父组件,父组件可以决定这些回传的数据是以何种结构或者外观在子组件内部去展示

特点:可以将数据回传给父组件

//子组件
<slot :$row="item"></slot>
<script setup>
  const item={title:"稀土掘金"}
</script>
//父组件
<template v-slot="{$row}">
  <span>{{ $row.title }}</span>
</template> 

mitt

vue3里面EventBus被去掉了!查了查发现vue3推荐我们使用mitt。因为mitt官方文档是与框架无关的,需要我们自行安装。

定义mitt

import mitt from 'mitt'
const $bus = mitt()
export default $bus

在组件中使用

传递数据:$bus.emit('key',data)

两个参数:第一个参数就是提供的数据key,第二个参数即祖先组件提供的数据

//$bus.emit用来传递数据
$bus.emit('one',{car:'奔驰'})

接收数据:$bus.on('key',callback)

一个参数:提供的数据key

一个回调方法:拿到数据后的处理

$bus.on('one',(car)=>{ console.log(car)})