- Props 和 Events:
- Props:父组件向子组件传递数据。在子组件中通过
props
定义接收数据。 - Events(emit):子组件向父组件发送消息或数据。子组件使用
$emit
方法触发事件,父组件监听这些事件。
- Props:父组件向子组件传递数据。在子组件中通过
- Provide / Inject:
- 这是一种在组件树之间进行通信的高级方法,允许一个祖先组件“提供”数据给所有的后代组件,无论它们在组件树中的深度如何。后代组件可以选择性地“注入”这些数据。
- Reactive References(如
ref
和reactive
):- 使用 Vue 的响应性系统,可以通过共享响应性引用(如使用
ref
或reactive
创建的变量)来在组件之间共享状态。
- 使用 Vue 的响应性系统,可以通过共享响应性引用(如使用
- Vuex:
- Vuex 是 Vue 的官方状态管理库,适用于大型应用程序。它提供了一个集中存储管理所有组件的状态,并以一种可预测的方式来进行状态更新。
- Event Bus(已不推荐):
- 以前版本中常用 Event Bus 进行组件间通信,但在 Vue 3 中不再推荐使用,因为它可能会导致代码难以维护和测试。Vue 3 更推荐使用提供的组合式 API 和提供/注入方法。
- Global Properties(全局属性):
- 在 Vue 3 中,可以使用
app.config.globalProperties
定义全局属性,从而在多个组件中访问共享数据。这种方法虽然方便,但应谨慎使用,以避免过度依赖全局状态。
- 在 Vue 3 中,可以使用
defineProps代理
defineProps()系统自带 代理 只读
父组件向子组件传递数据。在子组件中通过 props
定义接收数据。
<script setup>
const props = defineProps({
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object
});
// script 代码区域不能省去props.
console.log(props.title);
</script>
<template>
<div>
<h1>{{ title }}</h1> 可以直接使用 不用props.
<!-- 使用其他 props -->
</div>
</template>
自定义事件
在 Vue 中,处理原生 DOM 事件主要涉及监听那些在 Vue 组件的根元素上没有被自动绑定的事件。Vue 提供了 .native 修饰符来帮助监听这些事件,但需要注意的是,在 Vue 3 中,.native 修饰符已被废弃。
原生DOM 事件
子组件可以使用 this.$emit(eventName, [...args]) 方法来触发一个事件,其中 eventName 是事件的名称,[...args] 是传递给监听器的参数
<!-- 子组件 -->
<template>
<button @click="sendData">Send Data</button>
</template>
<script>
export default {
methods: {
sendData() {
this.$emit('send-message', 'Hello from child!');
}
}
}
</script>
父组件监听子组件发出的事件,使用 v-on:eventName 或简写 @eventName
<!-- 父组件 -->
<template>
<ChildComponent @send-message="handleMessage"/>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
methods: {
handleMessage(msg) {
console.log('Message received:', msg);
}
}
}
</script>
自定义Event事件
子组件向父组件发送消息或数据。子组件使用 $emit
方法触发事件,父组件监听这些事件。
子组件可以使用 this.$emit(eventName, [...args]) 方法来触发一个事件,其中 eventName 是事件的名称,[...args] 是传递给监听器的参数
<script>
export default {
emits: ['send-message'],
methods: {
sendData() {
this.$emit('send-message', 'Hello from child!');
}
}
}
</script>
在 <script setup>
中使用 defineEmits:这是一个编译时宏 vue 自带,用于在使用 <script setup>
语法时声明事件
<script setup>
const emit = defineEmits(['send-message']);
const sendData = () => {
emit('send-message', 'Hello from child!');
}
</script>
全局事件总线
mitt 提供了一种简洁而有效的方法来在 Vue 3 中实现全局或局部的事件通信,非常适合需要跨组件通信但又不足以使用 Vuex 或 Pinia 这样的全局状态管理方案的场景。
// eventBus.js
import mitt from 'mitt';
const emitter = mitt();
export default emitter;
<script setup>
import emitter from './eventBus';
// 发射事件
function sendEvent() {
emitter.emit('my-event', 'Hello World!');
}
// 监听事件
onMounted(() => {
emitter.on('my-event', (message) => {
console.log(message);
});
});
// 组件卸载时,移除监听器
onUnmounted(() => {
emitter.off('my-event');
});
</script>
v-Model
v-model 在 Vue 中主要用于创建双向数据绑定,通常应用于表单元素(如输入框、选择框和开关)上。在 Vue 3 中,v-model 默认绑定到一个名为 modelValue 的 prop,并监听一个名为 update:modelValue 的事件
<template>
<input v-model="message" placeholder="Edit me">
</template>
<script setup>
import { ref } from 'vue';
const message = ref('');
</script>
在自定义组件上使用 v-model
在自定义组件上使用 v-model 时,你可以控制组件如何接收和发射值。这使得 v-model 在自定义组件上的使用变得非常灵活:
<!-- 子组件 -->
<template>
<input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)">
</template>
<script setup>
defineProps({
modelValue: String
});
</script>
多个 v-model 绑定
Vue 3 引入了在单个组件上使用多个 v-model 的能力。这是通过为每个 v-model 绑定一个不同的 prop 实现的,可以非常方便地管理组件的多个可变属性:
<!-- 子组件 -->
<template>
<input :value="firstName" @input="$emit('update:firstName', $event.target.value)">
<input :value="lastName" @input="$emit('update:lastName', $event.target.value)">
</template>
<script setup>
defineProps({
firstName: String,
lastName: String
});
</script>
<!-- 父组件 -->
<template>
<FullNameInput v-model:first-name="firstName" v-model:last-name="lastName" />
</template>
<script setup>
import { ref } from 'vue';
import FullNameInput from './FullNameInput.vue';
const firstName = ref('');
const lastName = ref('');
</script>
v-model 修饰符
Vue 3 保留了如 .lazy、.number 和 .trim 这样的 v-model 修饰符,用于定制如何处理用户输入:
.lazy:将数据同步从 input 事件更改为 change 事件。
.number:自动将用户输入转换为数值类型。
.trim:自动去除用户输入的首尾空白字符。
<template>
<input v-model.number="age" type="number">
<input v-model.trim="username">
</template>
<script setup>
import { ref } from 'vue';
const age = ref(0);
const username = ref('');
</script>