Skip to content

组件相互通信

组件之间通讯通常有父子组件之间通信、跨组件之间通信,框架中父子组件通信我们通常使用props和emit来实现,而跨组件通信我们使用事件总线来实现

1、父子组件通信

  • 父组件向子组件传递数据

父组件向子组件传递数据通过props方式,示例如下:

父组件:

ts
<template>
  <div>
    <ChildItem :name="name"></ChildItem>
  </div>
</template>
<script lang="ts" setup>
import ChildItem from './modules/ChildItem.vue'
const name = ref('张三')
</script>

子组件:

ts
<template>
  <div class="title">{{name}}</div>
</template>
<script lang="ts" setup>
const props = defineProps({
  name: {
    type: String,
    required: true
  }
})
</script>
  • 子组件向父组件传递数据

子组件向父组件传递数据通过自定义事件方式

父组件:

ts
<template>
  <div>
    <ChildItem @callback="handleCallback()"></ChildItem>
  </div>
</template>
<script lang="ts" setup>
import ChildItem from './modules/ChildItem.vue'
const handleCallback = (data) => {
  console.log(data)
}
</script>

子组件:

ts
<template>
  <div>
    <a-button @click="handleParentCallback()">点我回调</a-button>
  </div>
</template>
<script lang="ts" setup>
const emits = defineEmits(['callback'])
const handleParentCallback = () => {
  emits('callback', 'data')
}
</script>

2、跨组件通信

Vue2.x 使用 EventBus 事件总线进行兄弟组件通信,而在Vue3中事件总线模式已经被移除,官方建议使用外部的、实现了事件触发器接口的库, 例如 mitt

因此,框架中引入mitt进行跨组件通信,见utils/emmitter.ts,更多需求可在此文件中定义封装。

目前框架通过mitt中封装了关闭标签页的公共方法,实际使用如下:

ts
<template>
  <div>
    <a-button @click="handleClosePage()">关闭当前标签页</a-button>
  </div>
</template>
<script lang="ts" setup>
import { useRouter } from 'vue-router'
import { closePage } from '@/utils/emitter'

const userRouter = useRouter()

const handleClosePage = () => {
  const currentRoutePath = userRouter.currentRoute.value.fullPath
  closePage(currentRoutePath)
}
</script>