组件通信
组件通信
Props的创建和使用
父传递数据给子
一个vue文件相当于一个单文件组件,可以像积木一样加在别的组件中:
import todoListItem from 'todoListItem.vue'
//在script部分引入todoListItem
<todoListItem />
<!---在template中使用这个组件-->
但是,往往需要再子组件中获取到父组件所希望传入的值。比如在todoList.vue中:
<script setup lang="ts">
import {reactive} from 'vue'
let todos=reactive([
{work:"洗衣服",time:10},
{work:"洗碗",time:14},
{work:"洗澡",time:12},
{work:"洗车",time:15},
])
<script>
<template>
<div>
<ul>
<li v-for="todo, index in todos" :key="index"><todoListItem :work="todo.work" :time="todo.time"></todoListItem></li>
<ul>
</div>
<template/>
这里想要在todoListItem中显示出对应的work和time,需要用到自定义Prop
<script lang="ts" setup>
import {defineProps} form 'vue'
defineProps(['work','time'])
</script>
<template>
<div>
{{work}}--{{time}}min
</div>
</template>
Note:
想要在script标签中使用 Props传入的属性,需要用一个变量来接受这些props:
<script setup> let todo=defineProps(['work','time']) <script>
这里todo是一个对象,可以通过todo.work和todo.time来获取到对应的值。
但是在template中直接使用work和todo即可
在传入对应的组件的时候,需要区分传递字面量和表达式:
<todoListItem work="todo.work" time="todo.time" /> //传递的是字面量,即work和time都只是一个字符串 <todoListItem :work="todo.work" :time="todo.time" /> //传递的是exprssion,在这里evaluate之后得到的是变量
在用v-for遍历的时候,也需要使用' :key=".....id" ' 而非'key="...id"'
子传递数据给父
此时,可以创建一个有参数的函数作为Props:
在父组件中:
<script>
<Son :sonFunc="farFun"></Son>
function farFun(data){
//在这里就可以访问到子组件传递的数据
}
</script>
在子组件使用这个函数的时候需要传递参数:
const props=defineProps(['sonFunc'])
//......
sonFunc(data)
//......
自定义事件
在使用子组件的时候,除了可以有自定义的Props,还可以自定义events:
<script>
<Son @abc="farFunction"></Son>
function farFunction()
{
//the body of the fucntion
}
//abc是一个event,只有这个event被触发,函数就会调用
</script>
对应的,在子组件中,应该也要定义一个事件,并且在合适的时候触发这个事件:
<script>
import {defineEvent} from 'vue'
defineEvent(['abc'])
//.......在某些情况下
emit('abc')
//触发事件abc
</script>
Note1
emit中还可以传递参数,
emit('abc',arg1,arg2,arg3)
这个时候绑定这个事件的函数需要写成一个回调函数:
<ChildComponent @event-name="(arg1, arg2, arg3) => handleEvent(arg1, arg2, arg3)" />
Note2:
emit 只能在定义事件的组件中触发,父组件或其他组件无法直接通过emit触发子组件的事件
借助mitt通信
mitt在我看来就是提供了一个便于定义和触发事件的第三方库,借助事件可以传递参数(在触发事件的时候可以传递参数)
安装mitt
运行:
npm i mitt
这里使用的包管理软件是npm,其他的如pnpm和yarn自行查阅
创建事件总线
在src文件夹下面创建一个叫 'utils' 或者 'tools'的文件夹,再到这个子文件夹里面创建一个叫emitter.ts的文件:
import {mitt} from 'mitt'
const emitter=mitt()
export default emitter
监听/订阅事件===>定义某个事件
在想要订阅事件的组件内部引入emitter
在通信中,通常是接受数据的组件处订阅事件
<script>
import emitter from '@/utils/emitter'
emitter.on('事件名' (value)=>{
//回调函数,当该事件触发的时候,函数被调用
})
</script>
发送、发布事件===>触发某个事件
在想要触发某件的组件中发布事件
在通信中, 通常是发送数据的组件触发事件
<script>
import emmiter from '@/utils/emitter'
emmiter.emit('事件名',value)
</script>
补充:
- emitter.all ===>所有的事件
emitter.all.clear()===> 清除所有的事件
- emitter.off('事件名')===> 取消监听事件(相当于删除事件)