Vue3+(TS) 组件通信

246 阅读3分钟

1.props

// 父组件
<template>
    <div>
    <!-- 使用子组件 -->
      <son :son="son" :sendFun="sendFun" />
    </div>
</template>

<script lang="ts" setup>
import {ref} from "vue"
import son from "./son.vue"  // 引入子组件
const son = ref('传送过去的数据') // 传送给子组件的数据
const review = ref('子给父回传的数据') // 通过给子组件传一个函数,子组件触发函数传参

// 发送给子组件方法
const sendFun = (value:string)=>{
// 通过给子组件传一个函数,子组件触发函数传参
    review.value = value
}
</script>
//子组件
<template>
    <div>
    <!-- 使用父组件传送过来的数据 -->
         {{son}}
   
    <!-- 使用父组件传送过来的方法 -->
        <div @click = "sendFun('返回的数据')"></div>
     </div>
</template>

<script lang="ts" setup>
// 第一种声明接收方式
defineProps(['son','sendFun'])

// 第二种声明接收方式(对象型)
defineProps({
   son:{
      type:String,   // 声明类型
      default:'zzz',  // 默认值
      required:true,  // 该数据是否为必传
   }
})

// 还有泛型写法等等就不一一列举了(这里只列举了几种常用的方式)
</script>

2. 自定义事件

// 父组件
<template>
    <div>
    <!-- 使用子组件,绑定自定义事件 -->
      <son @sonFun = "sonFun" />
    </div>
</template>

<script lang="ts" setup>
import {ref} from "vue"
import son from "./son.vue"  // 引入子组件
// 自定义函数
const sonFun = (e)=>{
}
</script>
//子组件
<template>
    <div>   
    <!-- 点击事件触发,然后在事件中调用自定义方法 -->
        <div @click = "sendFun"></div>
     </div>
</template>

<script lang="ts" setup>
// 在子组件中声明事件
const emit = defineEmits(['sonFun'])

// 点击事件触发,然后在事件中调用自定义方法 
const sendFun = ()=>{
    emit('sonFun','传递的参数')
}
</script>

3. v-model

// 父组件
<template>
    <div>
    <!-- 使用子组件,绑定自定义事件 -->
      <son v-model="sonData" />
      <!-- 而且可以自定义名字用来传递多个v-model -->
      <son v-model:name="sonData" />
    </div>
// v-model 相当于干了两件事 1. v-bind绑定 2. @input事件
</template>

<script lang="ts" setup>
import {ref} from "vue"
import son from "./son.vue"  // 引入子组件
const sonData = ref('发送给组件的数据')
</script>
//子组件
<template>
    <div>   
    <!-- 父给子传递的数据 -->
        <div @click = "sendFun">{{modelValue}}</div>
     </div>
</template>

<script lang="ts" setup>
// 在子组件中声明,如果不自定义名字的话则默认为modelValue
defineProps(['modelValue','name'])
// 声明自定义接收方式,相当于v-model同时进行了props传参和自定义事件双向绑定
const emit = defineEmits(['update:modelValue','update:name'])
// 点击事件触发,然后在事件中调用自定义方法 
const sendFun = ()=>{
    // 传递过去后,父组件的sonData 会改为下面传递的数据
    emit('update:modelValue','传递的参数')
}
</script>

4. $attrs

用于当前组件的父组件给当前组件的子组件通信,祖孙通信

// 父组件
<template>
    <son :data="data" :upData="upData"/>
</template>

<script lang = "ts" setup>
// 引入子组件
import son from './son'
const data = ref('数据')
// 可以通过传递函数实现孙给父通信
const upData = (value)=>{

}
</script>
// 子组件
<template>
    <div>
        <!-- 将数据直接传给孙组件 -->
        <grandChild v-bind="$attrs"/>
    </div>
</template>

<script lang = "ts" setup>
// 引入孙组件
import grandChild from './grandChild'
// 不需要对父组件传的props进行接收,因为在$attrs里存着直接给孙组件
</script>
// 孙组件
<template>
</template>

<script lang = "ts" setup>
// 孙组件对数据进行接收
defindProps(['data',"upData"])
</script>

5. parent、refs

refs父传子,refs 父传子,parent子传父

// 父组件
<template>
    <div>
      <div @click="changeSon"></div>
        <son ref="child"/>
           <!-- $refs 可以拿到所有的子组件 -->
         <div @click="changeSonTwo($refs)"></div>
     </div>
</template>

<script lang = "ts" setup>
// 引入子组件
import son from './son'
const child = ref()

const data = ref('暴露给子组件的数据')
// 父组件暴露数据给子组件
defineExpose({data})

// 拿到dom后可以拿到子组件对外暴露的数据
function changeSon (){
    console.log( child.value.data1,child.value.data2)
}

// 可以拿到所以子组件,前提是需要给子组件绑定ref值
function changeSonTwo(refs:object){
     console.log(refs.child)
}
</script>
// 子组件
<template>
    <div>
    <grandChild v-bind="$attrs"/>
        <!-- 修改父组件 -->
    <div @click="changeFa($parent)"></div>
    </div>
</template>

<script lang = "ts" setup>
cosnt data1 = ref('对外暴露的数据1')
const data2 = ref('对外暴露的数据2')
// 对外进行暴露
defineExpose({data1,datat2})

// 修改父组件,这个parent就是父组件
const changeFa = (parent)=>{
    
}
</script>

6. provide-inject

祖孙通信

// 父组件
<template>
    <div>
      <div @click="changeSon"></div>
        <son ref="child"/>
         
     </div>
</template>

<script lang = "ts" setup>
const money = ref(100)
// 引入子组件
import son from './son'
// 需要引入provide
import {provide} from "vue"
// 需要传入两个参数,1.数据名字,2. 数据值
    provide('money',{money,update}) //money为ref数据,但是传的时候不需要.value
// 传给孙组件一个函数,用来实现孙给父组件传值
function update(value){
    
}
</script>
// 子组件
<template>
    <div>
        <child />
     </div>
</template>

<script lang = "ts" setup>
// 引入孙组件
import child from './child'
</script>
// 孙组件
<template>
    <div>
        <!-- 调用函数给父组件传值 -->
      <div @click="update('传值')"></div>
     </div>
</template>

<script lang = "ts" setup>
// 需要引入inject进行接收
import {inject} from "vue"
// 参数 1. 数据对应名字 2. 默认值
let {money,update} = inject('money',{money:200,update:(x:number)=>{}})

</script>

7. mitt

任意组件通信 需要安装mitt pnpm install mitt

// mitt.ts
    import mitt from 'mitt' // 引入mitt
    
    const emitter = mitt()  // 调用mitt,emitter能绑定事件,触发事件
    
    export default emitter  // 暴露mitt
import emitter from './mitt'
// 绑定事件
emitter.on('fun1',(v)=>{
    console.log('fun1被调用',v)
})

// 触发事件
emitter.emit('fun1','传递的参数')

// 解绑事件
emitter.off('fun1')
// 一次性解绑所有事件
emitter.all.clear()