组件通信
- 一.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