vue 组件间通信分为 :
- 父组件向子组件通信
- 子组件向父组件通信
- 兄弟间组件通信
首先什么是父子组件
一个组件引入了另外一个组件,那么被引入的组件是子组件
代码演示一下 在 components 有两个 vue 文件,Father.vue 以及 Son.vue
在 Father.vue 引入 Son.vue 的组件
那么 Father.vue 是 Son.vue 的父组件 ,Son.vue 是 Father.vue 的子组件
接下来演示下父子组件间通信
父组件向子组件通信
在用 vite 构建 vue 项目,就已经自动生成了父组件向子组件的通信。父组件向子组件通信的关键是defineProps函数
代码演示一下 父组件向子组件传递一个字符串,子组件接收这个字符串并展示出来
Father.vue
<script setup lang="ts">
import Son from './Son.vue'
</script>
<template>
<Son msg="这信息来自父组件" /></Son>
</template>
Son.vue
<script setup lang="ts">
defineProps<{msg:string}>()
</script>
<template>
<div class="son">
子组件内容:
<p></p>
<div>{{msg}}</div>
</div>
</template>
这里要特别注意的是 defineProps 在 typescript 的专用写法:defineProps<>() ,而且 defineProps 是在 setup 语法糖才能使用, defineProps无须引入,直接使用即可
运行后是这样:
子组件向父组件通信
子组件向父组件通信的关键是defineEmits函数
Son.vue 通过 defineEmits 定义事件传递方法 toFather
<script setup lang="ts">
const emit = defineEmits<{(e:'toFather',msg:string):void}>()
const click = () =>{
emit('toFather','来自子组件信息')
}
</script>
<template>
<div class="son">
子组件内容:
<p></p>
<button @click="click">
点击传信息给父组件
</button>
</div>
</template>
同样要注意的是 defineEmits 在 typescript 的专用写法:defineEmits<{}>() ,而且 defineEmits 是在 setup 语法糖才能使用, defineEmits无须引入,直接使用即可
在 Father.vue ,vscode 可以提示出 Son.ve 定义的事件传递方法 toFather
完整的 Father.vue 代码:
<script setup lang="ts">
import {ref} from 'vue'
import Son from './Son.vue'
const msg = ref('我是父组件')
const getSonMsg = (val:string) => {
msg.value = val
}
</script>
<template>
<div class="father">
父组件内容:
<p></p>
{{msg}}
</div>
<Son @to-father="getSonMsg" ></Son>
</template>
运行:
兄弟组件间通信
兄弟组件通信可以理解为:父组件接受了 子组件1 的传递事件,然后父组件调用 子组件2 的方法,从而达到兄弟组件通信
建 两个 子组件 以及 一个 父组件
Son1.vue 和 Father.vue 就是子组件向父组件传递事件,这里就直接上代码:
Son1.vue
<script setup lang="ts">
const emit = defineEmits<{(e:'toFather',msg:string):void}>()
const click = () =>{
emit('toFather','来自组件"Son-1"信息')
}
</script>
<template>
<div class="son1">
组件 son-1 内容:
<p></p>
<button @click="click">
点击传信息给'Son-2'组件
</button>
</div>
</template>
Father.vue
<script setup lang="ts">
import {ref} from 'vue'
import Son1 from './Son1.vue'
import Son2 from './Son2.vue'
const getSonMsg = () => {
}
</script>
<template>
<Son1 @to-father="getSonMsg" ></Son1>
</template>
重点是 Son2.vue ,需要使用defineExpose 曝露方法,这样父组件才能调用 Son2 组件的这个方法
Son2.vue 定义更改属性的方法:接受的值是字符串,这个值就是 Son-1 组件传过来的值
接着 Son2.vue 要曝露这个方法,以及给这个方法指定类型,这个一定要注意
完整的 Son2.vue :
<script setup lang="ts">
import {ref} from 'vue'
export interface ExposeType {
getOtherMsg:Function
}
const msg = ref('我是组件 son-2')
const getOtherMsg = (val:string) => {
msg.value = val
}
defineExpose({
getOtherMsg
})
</script>
<template>
<div class="son2">
组件 son-2 内容:
<p></p>
{{msg}}
</div>
</template>
</template>
最后看一下 Father.vue 如何调用 Son2.vue 曝露的方法, 首先是引入 Son2 组件 以及 Son2曝露方法的类型
然后在 接手 Son1 组件方法里调用 Son2 曝露的方法,实现 Son1组件传递的值传递给 Son2
而且 vscode 是能识别 Son2 的这个曝露方法
完整的 Father.vue 代码:
<script setup lang="ts">
import {ref} from 'vue'
import Son1 from './Son1.vue'
import Son2,{ExposeType} from './Son2.vue'
const msg = ref<ExposeType | null>(null)
const getSonMsg = (val:string) => {
if(msg.value) msg.value.getOtherMsg(val)
}
</script>
<template>
<Son1 @to-father="getSonMsg" ></Son1>
<Son2 ref="msg"></Son2>
</template>
运行一下:
总结
- 父组件向子组件传值:子组件通过
defineProps 接收传值 - 子组件向父组件传递事件:子组件通过
defineEmits 传递事件 - 兄弟组件通信:父组件获取子组件传递事件,并调用子组件
defineExpose 曝露的方法。
|