组件通信
- 一.props(父<=>子)
- 二.自定义事件(子=>父)
- 三.mitt(实现任意组件通信)
- 四.v-model(父<=>子)
- (1).v-model的本质
- (2).组件标签中v-model的本质
- (3).$event到底是什么
概况
一.props(父<=>子)
使用频率最高
若 父传子:属性值是非函数。
若 子传父:属性值是函数。
父组件:
<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>
二.自定义事件(子=>父)
emit()传递事件名和具体参数
defineEmit()声明可以触发的事件
原生事件:
1.事件名是特定的(click、mosueenter等等)
2.事件对象$event: 是包含事件相关信息的对象(pageX、pageY、target、keyCode)
自定义事件:
1.事件名是任意名称
2.事件对象$event: 是调用emit时所提供的数据,可以是任意类型!!!
3.命名方式尽量不要驼峰式,而是采取keybab-case式,即send-toy
父组件
<template><div class="father"><h3>父组件</h3><h4 v-show="toy">子给的玩具:{{ toy }}</h4><!-- 给子组件Child绑定事件 --><Child @send-toy="saveToy"/></div>
</template><script setup lang="ts" name="Father">import Child from './Child.vue'import { ref } from "vue";// 数据let toy = ref('')// 用于保存传递过来的玩具function saveToy(value:string){console.log('saveToy',value)toy.value = value}
</script>
子组件
<template><div class="child"><h3>子组件</h3><h4>玩具:{{ toy }}</h4>//当点击按钮时会触发 emit 函数,//并传递 'send-toy' 作为事件名和 toy 的值作为参数。<button @click="emit('send-toy',toy)">测试</button></div>
</template>
<script setup lang="ts" name="Child">import { ref } from "vue";// 数据let toy = ref('奥特曼')// 使用 defineEmits 函数声明了组件可以触发的自定义事件。//在这里声明了 send-toy 这个事件。const emit = defineEmits(['send-toy'])
</script>
三.mitt(实现任意组件通信)
接收数据的:提前绑好事件(提前订阅消息)
传递数据的:在合适的时机触发事件(发布消息)
1.先安装
npm i mitt
2.在src\utils\emitter.ts下配置
3.使用
on 绑定事件
emit 触发事件
off 移除事件
all.clear 移除全部事件
// 绑定事件abc,abc事件被触发时调用箭头函数emitter.on('abc',(value)=>{console.log('abc事件被触发',value)})emitter.on('xyz',(value)=>{console.log('xyz事件被触发',value)})setInterval(() => {// 触发事件emitter.emit('abc',666)emitter.emit('xyz',777)}, 1000);setTimeout(() => {// 清理事件emitter.all.clear()}, 3000);
接收数据和传递数据的组件都需要引入
eg:两个兄弟组件传递数据
接收数据的组件中:绑定事件、同时在销毁前解绑事件
<template><div class="child2"><h3>子组件2</h3><h4>电脑:{{ computer }}</h4><h4>哥哥给的玩具:{{ toy }}</h4></div>
</template><script setup lang="ts" name="Child2">import {ref,onUnmounted} from 'vue'import emitter from '@/utils/emitter';// 数据let computer = ref('联想')let toy = ref('')// 给emitter绑定send-toy事件emitter.on('send-toy',(value:any)=>{toy.value = value})// 在组件卸载时解绑send-toy事件onUnmounted(()=>{emitter.off('send-toy')})
提供数据的组件,在合适的时候触发事件
template><div class="child1"><h3>子组件1</h3><h4>玩具:{{ toy }}</h4><button @click="emitter.emit('send-toy',toy)">玩具给弟弟</button></div>
</template><script setup lang="ts" name="Child1">import {ref} from 'vue'import emitter from '@/utils/emitter';// 数据let toy = ref('奥特曼')
</script>
四.v-model(父<=>子)
(1).v-model的本质
表单的双向绑定
<!-- 使用v-model指令 -->
<input type="text" v-model="userName"><!-- v-model的本质是下面这行代码 -->
<input type="text" :value="userName" @input="userName =(<HTMLInputElement>$event.target).value"
>
注意点
- (&event.target)这个是ts的类型断言,target一定是html元素而不为空
- 数据到页面:value=“userName”
- 页面到数据 :
@input=“userName =(<HTMLInputElement》$event.target).value”
(2).组件标签中v-model的本质
(3).$event到底是什么
对于原生事件,$event就是事件对象====>能.target
对于自定义事件,$event就是触发事件时,所传递的对象====>不能.target