Vue3组件通信

Vue3组件通信和Vue2的区别:

1、移出事件总线,使用mitt代替

2、vuex换成了pinia

3、.sync优化到了v-model里面了

4、把$listeners所有的东西,合并到$attrs中了

5、$children被砍掉了

props

若 父传子:属性值是非函数。若 子传父:属性值是函数

父传递给子,是以属性的方式传递,子组件通过defineProps去接收

子传递给父,父组件需要创建一个函数去接取,并通过属性传给子组件,子组件通过defineProps去调用那个方法

//父组件
<template>
  <div class="father">
    <h3>父组件,</h3>
        <h4>我的车:{{ car }}</h4>
        <h4>儿子给的玩具:{{ toy }}</h4>
        <Child :car="car" :getToy="getToy"/>
  </div>
</template>
<script setup lang="ts" name="Father">
    import Child from './Child.vue'
    import { ref } from "vue";
    // 数据
    const car = ref('奔驰')
    const toy = ref()
    // 方法
    function getToy(value:string){
        toy.value = value
    }
</script>


//子组件
<template>
  <div class="child">
    <h3>子组件</h3>
        <h4>我的玩具:{{ toy }}</h4>
        <h4>父给我的车:{{ car }}</h4>
        <button @click="getToy(toy)">玩具给父亲</button>
  </div>
</template>
<script setup lang="ts" name="Child">
    import { ref } from "vue";
    const toy = ref('奥特曼')
    defineProps(['car','getToy'])
</script>

自定义事件

自定义事件常用于:子 => 父

注意区分好:原生事件、自定义事件

原生事件:

  • 事件名是特定的(clickmosueenter等等)
  • 事件对象$event: 是包含事件相关信息的对象(pageXpageYtargetkeyCode

自定义事件

  • 事件名是任意名称
  • 事件对象$event: 是调用emit时所提供的数据,可以是任意类型!!!
//父组件
<template>
  <div class="father">
    <h3>父组件,</h3>
        <h4>我的车:{{ car }}</h4>
        <h4>儿子给的玩具:{{ toy }}</h4>
        <Child @send-toy="saveToy"/>
  </div>
</template>
<script setup lang="ts" name="Father">
    import Child from './Child.vue'
    import { ref } from "vue";
    // 数据
    const car = ref('奔驰')
    const toy = ref('')
    // 方法
    function saveToy(value:string){
        toy.value = value
    }
</script>


//子组件
<template>
  <div class="child">
    <h3>子组件</h3>
        <h4>我的玩具:{{ toy }}</h4>
        <button @click="emit('send-toy',toy)">玩具给父亲</button>
  </div>
</template>
<script setup lang="ts" name="Child">
    import { ref } from "vue";
    const toy = ref('奥特曼')
    const emit = definEmits(['send-toy'])
</script>

mitt (任意组件通信)

构建mitt

npm i mitt  下载mitt依赖    体积极小,只有200B字节

在utils文件夹下,创建emitter.ts文件

//引入mitt
import mitt from 'mitt'

//调用mitt得到emitter,emitter能:绑定事件、触发事件
const emitter = mitt()

//暴露emitter
export default emitter

引入mtt

在main.ts里   import emitter from '@/utils/emitter'   

使用mitt

//引入mitt
import mitt from 'mitt'

//调用mitt得到emitter,emitter能:绑定事件、触发事件
const emitter = mitt()

//绑定事件
emitter.on('test1',()=>{
    console.log('test1')
})
emitter.on('test2',()=>{
    console.log('test2')
})

//触发事件 此为立即执行
emitter.emit('test1')

//解绑事件
emitter.off('test1')  //相对于关闭了函数

//解绑所有
emitter.all.clear()


//暴露emitter
export default emitter

具体使用

一个父组件中的两个兄弟组件间的相互通信

父组件

<template>
    <div>
        <child_one></child_one> //兄
        <child_two></child_two>  //弟
    </div>
</template>

<script>
    import childOne form './childone.vue' 
    import childTwo form './childtwo.vue' 
</script>

<template>
    <div class="child_one">
       <h2>兄</h2>
        <button @click="emitter.emit('send-toy',toy)"> 传递 </button>
    </div>
</template>

<script setup>
    import { ref } from 'vue'
    import emitter from '@/utils/emitter'

    let toy = ref('哥哥的东西')
</script>

<template>
    <div class="child_one">
       <h2>弟</h2>
       <div> {{ toy }} </div>
    </div>
</template>

<script setup>
    import { ref,onUnmounted } from 'vue'
    import emitter from '@/utils/emitter'

    let toy = ref('')

    //给emitter绑定send-toy事件
    emitter.on('send-toy',(value:any)=>{
        toy.value = value
    })

    //在组件卸载时解绑send-toy事件
    onUnmounted(()=>{
        emitter.off('send-toy')
    })
</script>

以上,在兄组件点击传送数据后,弟组件就能收到数据。其实不单单是兄弟,只要是引入了mitt,就可以做到跨组件通信

provide和inject

<template>
  <div class="father">
    <h3>父组件</h3>
    <h4>资产:{{ money }}</h4>
    <h4>汽车:{{ car }}</h4>
    <button @click="money += 1">资产+1</button>
    <button @click="car.price += 1">汽车价格+1</button>
    <Child/>
  </div>
</template>
<script setup lang="ts" name="Father">
  import Child from './Child.vue'
  import { ref,reactive,provide } from "vue";
  // 数据
  let money = ref(100)
  let car = reactive({
    brand:'奔驰',
    price:100
  })
  // 用于更新money的方法
  function updateMoney(value:number){
    money.value += value
  }
  // 提供数据
  provide('moneyContext',{money,updateMoney})
  provide('car',car)
</script>
<template>
  <div class="grand-child">
    <h3>我是孙组件</h3>
    <h4>资产:{{ money }}</h4>
    <h4>汽车:{{ car }}</h4>
    <button @click="updateMoney(6)">点我</button>
  </div>
</template>
<script setup lang="ts" name="GrandChild">
  import { inject } from 'vue';
  // 注入数据
 let {money,updateMoney} = inject('moneyContext',{money:0,updateMoney:(x:number)=>{}})
  let car = inject('car')
</script>

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值