1. Props 和 Events
Props:父组件通过 props 向子组件传递数据。
Events:子组件通过 $emit 向父组件发送事件。
<!-- ParentComponent.vue -->
<template>
<ChildComponent :message="parentMessage" @update-message="updateMessage" />
</template>
<script setup lang="ts">
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const parentMessage = ref('Hello from parent');
function updateMessage(newMessage: string) {
parentMessage.value = newMessage;
}
</script>
<!-- ChildComponent.vue -->
<template>
<div>
<p>{{ message }}</p>
<button @click="sendMessage">Send Message</button>
</div>
</template>
<script setup lang="ts">
const props = defineProps<{
message: string;
}>();
const emit = defineEmits<{
(e: 'update-message', message: string): void;
}>();
function sendMessage() {
emit('update-message', 'Hello from child');
}
</script>
2. Provide / Inject
Provide:祖先组件通过 provide 提供数据。
Inject:后代组件通过 inject 获取数据。
<!-- AncestorComponent.vue -->
<template>
<DescendantComponent />
</template>
<script setup lang="ts">
import { provide, ref } from 'vue';
import DescendantComponent from './DescendantComponent.vue';
const message = ref('Hello from ancestor');
provide('message', message);
</script>
<!-- DescendantComponent.vue -->
<template>
<div>
<p>{{ injectedMessage }}</p>
</div>
</template>
<script setup lang="ts">
import { inject } from 'vue';
const injectedMessage = inject('message');
</script>
3. Event Bus
使用一个全局的 Vue 实例作为事件总线,组件可以通过它来发布和订阅事件。
// eventBus.ts
import { createApp } from 'vue';
export const eventBus = createApp({});
// ComponentA.vue
<script setup lang="ts">
import { eventBus } from './eventBus';
function sendMessage() {
eventBus.config.globalProperties.$emit('message', 'Hello from Component A');
}
</script>
// ComponentB.vue
<script setup lang="ts">
import { onMounted } from 'vue';
import { eventBus } from './eventBus';
onMounted(() => {
eventBus.config.globalProperties.$on('message', (message: string) => {
console.log(message);
});
});
</script>
4. Reactive State
使用 Vue 的 reactive 或 ref 创建一个全局状态对象,组件之间共享这个状态。
// sharedState.ts
import { reactive } from 'vue';
export const state = reactive({
message: 'Hello from shared state',
});
// ComponentA.vue
<script setup lang="ts">
import { state } from './sharedState';
function updateMessage() {
state.message = 'Updated message from Component A';
}
</script>
// ComponentB.vue
<template>
<div>
<p>{{ state.message }}</p>
</div>
</template>
<script setup lang="ts">
import { state } from './sharedState';
</script>
5. Composables
使用 Vue 3 的 Composition API 创建可重用的逻辑,组件之间共享状态和逻辑。
// useSharedState.ts
import { ref } from 'vue';
export function useSharedState() {
const message = ref('Hello from composable');
function updateMessage(newMessage: string) {
message.value = newMessage;
}
return { message, updateMessage };
}
// ComponentA.vue
<script setup lang="ts">
import { useSharedState } from './useSharedState';
const { message, updateMessage } = useSharedState();
function changeMessage() {
updateMessage('Updated message from Component A');
}
</script>
// ComponentB.vue
<template>
<div>
<p>{{ message }}</p>
</div>
</template>
<script setup lang="ts">
import { useSharedState } from './useSharedState';
const { message } = useSharedState();
</script>
6. Teleport
使用 Teleport 将组件渲染到 DOM 中的其他位置,适用于模态框、通知等场景。
<!-- ParentComponent.vue -->
<template>
<div>
<button @click="showModal = true">Show Modal</button>
<Teleport to="body">
<ModalComponent v-if="showModal" @close="showModal = false" />
</Teleport>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import ModalComponent from './ModalComponent.vue';
const showModal = ref(false);
</script>
<!-- ModalComponent.vue -->
<template>
<div class="modal">
<p>This is a modal</p>
<button @click="$emit('close')">Close</button>
</div>
</template>
<script setup lang="ts">
defineEmits(['close']);
</script>
7. Custom Directives
使用自定义指令在组件之间传递数据或执行操作。
// v-my-directive.ts
import { DirectiveBinding } from 'vue';
export const myDirective = {
mounted(el: HTMLElement, binding: DirectiveBinding) {
el.addEventListener('click', () => {
console.log('Directive triggered with value:', binding.value);
});
},
};
// ComponentA.vue
<template>
<button v-my-directive="'Hello from directive'">Click me</button>
</template>
<script setup lang="ts">
import { myDirective } from './v-my-directive';
</script>
8. Global Properties
使用 app.config.globalProperties 添加全局属性或方法,所有组件都可以访问。
// main.ts
import { createApp } from 'vue';
import App from './App.vue';
const app = createApp(App);
app.config.globalProperties.$myGlobalFunction = () => {
console.log('Hello from global function');
};
app.mount('#app');
// ComponentA.vue
<script setup lang="ts">
import { getCurrentInstance } from 'vue';
const instance = getCurrentInstance();
instance?.proxy?.$myGlobalFunction();
</script>
9. Custom Events with mitt
使用第三方库 mitt 来实现轻量级的事件总线。
npm install mitt
// eventBus.ts
import mitt from 'mitt';
export const eventBus = mitt();
// ComponentA.vue
<script setup lang="ts">
import { eventBus } from './eventBus';
function sendMessage() {
eventBus.emit('message', 'Hello from Component A');
}
</script>
// ComponentB.vue
<script setup lang="ts">
import { onMounted } from 'vue';
import { eventBus } from './eventBus';
onMounted(() => {
eventBus.on('message', (message: string) => {
console.log(message);
});
});
</script>
10. Context API
使用 Vue 3 的 provide 和 inject 来实现类似 React Context 的功能。
// context.ts
import { provide, inject, ref } from 'vue';
const MessageSymbol = Symbol();
export function provideMessage() {
const message = ref('Hello from context');
provide(MessageSymbol, message);
}
export function useMessage() {
const message = inject(MessageSymbol);
if (!message) {
throw new Error('Message not provided');
}
return message;
}
// ParentComponent.vue
<script setup lang="ts">
import { provideMessage } from './context';
import ChildComponent from './ChildComponent.vue';
provideMessage();
</script>
<template>
<ChildComponent />
</template>
// ChildComponent.vue
<script setup lang="ts">
import { useMessage } from './context';
const message = useMessage();
</script>
<template>
<div>
<p>{{ message }}</p>
</div>
</template>