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>
自定义事件
自定义事件常用于:子 => 父
注意区分好:原生事件、自定义事件
原生事件:
- 事件名是特定的(
click、mosueenter等等) - 事件对象
$event: 是包含事件相关信息的对象(pageX、pageY、target、keyCode)
自定义事件
- 事件名是任意名称
- 事件对象
$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>
1246

被折叠的 条评论
为什么被折叠?



