我通过ChatGpt复习Vue第四天

vue3 组件通信

1. 父子组件通信

1.1 使用 props 传递数据

在父组件中,通过 props 向子组件传递数据:

<!-- ParentComponent.vue -->
<template>
  <ChildComponent :message="parentMessage" />
</template>

<script setup>
import { ref } from 'vue'
import ChildComponent from './ChildComponent.vue'

const parentMessage = ref('Hello from Parent')
</script>
<!-- ChildComponent.vue -->
<template>
  <div>{{ message }}</div>
</template>

<script setup>
import { defineProps } from 'vue'

const props = defineProps({
  message: String
})
</script>

1.2 使用 $emit 传递事件

子组件通过 $emit 向父组件传递事件及数据:

<!-- ParentComponent.vue -->
<template>
  <ChildComponent @childEvent="handleEvent" />
</template>

<script setup>
function handleEvent(data) {
  console.log('Received from child:', data)
}
</script>
<!-- ChildComponent.vue -->
<template>
  <button @click="emitEvent">Click me</button>
</template>

<script setup>
import { defineEmits } from 'vue'

const emit = defineEmits(['childEvent'])

function emitEvent() {
  emit('childEvent', 'Data from Child')
}
</script>

2. 兄弟组件通信

2.1 使用事件总线(Event Bus)

虽然 Vue 3 中不再默认支持全局事件总线,但可以通过创建一个独立的事件总线来实现兄弟组件之间的通信。

// eventBus.js
import { reactive } from 'vue'

export const eventBus = reactive({
  emit(event, payload) {
    if (this[event]) {
      this[event](payload)
    }
  },
  on(event, callback) {
    this[event] = callback
  }
})

在两个兄弟组件中使用 eventBus 进行通信:

<!-- BrotherComponentA.vue -->
<template>
  <button @click="sendData">Send Data to B</button>
</template>

<script setup>
import { eventBus } from './eventBus'

function sendData() {
  eventBus.emit('dataFromA', 'Hello from A')
}
</script>
<!-- BrotherComponentB.vue -->
<template>
  <div>{{ receivedData }}</div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { eventBus } from './eventBus'

const receivedData = ref('')

onMounted(() => {
  eventBus.on('dataFromA', (data) => {
    receivedData.value = data
  })
})
</script>

2.2 使用 Vuex 或 Pinia(状态管理)

当兄弟组件之间的数据共享和同步需求较多时,使用状态管理工具如 Vuex 或 Pinia 会更加适合。

// store.js (using Pinia)
import { defineStore } from 'pinia'

export const useMainStore = defineStore('main', {
  state: () => ({
    sharedData: ''
  }),
  actions: {
    updateData(newData) {
      this.sharedData = newData
    }
  }
})

在组件中使用该状态:

<!-- BrotherComponentA.vue -->
<template>
  <button @click="sendData">Send Data to B</button>
</template>

<script setup>
import { useMainStore } from './store'
const store = useMainStore()

function sendData() {
  store.updateData('Hello from A')
}
</script>
<!-- BrotherComponentB.vue -->
<template>
  <div>{{ store.sharedData }}</div>
</template>

<script setup>
import { useMainStore } from './store'
const store = useMainStore()
</script>

3. 通过 provide 和 inject 进行祖孙组件通信

provide 和 inject 允许祖孙组件之间进行通信,而无需通过中间的父组件传递数据。

<!-- GrandparentComponent.vue -->
<template>
  <ParentComponent />
</template>

<script setup>
import { provide } from 'vue'
import ParentComponent from './ParentComponent.vue'

provide('sharedData', 'Hello from Grandparent')
</script>
<!-- ChildComponent.vue -->
<template>
  <div>{{ data }}</div>
</template>

<script setup>
import { inject } from 'vue'

const data = inject('sharedData')
</script>

4. 通过 Teleport 将内容传送到其他 DOM

Vue 3 引入了 Teleport 组件,可以将子组件的内容传送到 DOM 树中的其他位置,这在需要全局弹窗或模态框时非常有用。

<!-- TeleportExample.vue -->
<template>
  <button @click="showModal = true">Open Modal</button>

  <teleport to="body">
    <div v-if="showModal" class="modal">
      <p>This is a modal</p>
      <button @click="showModal = false">Close</button>
    </div>
  </teleport>
</template>

<script setup>
import { ref } from 'vue'

const showModal = ref(false)
</script>

<style>
.modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: white;
  padding: 20px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
</style>

5. 通过 emit 和 on 监听全局事件

Vue 3 中可以使用全局的 app.config.globalProperties 对象来注册和触发全局事件。

// main.js
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

app.config.globalProperties.$bus = {
  events: {},
  emit(event, data) {
    if (this.events[event]) {
      this.events[event](data)
    }
  },
  on(event, handler) {
    this.events[event] = handler
  }
}

app.mount('#app')

在组件中使用全局事件总线:

<!-- ComponentA.vue -->
<template>
  <button @click="sendData">Send Global Event</button>
</template>

<script setup>
import { getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance()

function sendData() {
  proxy.$bus.emit('globalEvent', 'Hello World')
}
</script>
<!-- ComponentB.vue -->
<template>
  <div>{{ receivedData }}</div>
</template>

<script setup>
import { ref, getCurrentInstance, onMounted } from 'vue'
const { proxy } = getCurrentInstance()
const receivedData = ref('')

onMounted(() => {
  proxy.$bus.on('globalEvent', (data) => {
    receivedData.value = data
  })
})
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值