本系列将从零开始,系统性地介绍 Vue 3 的常用 API,逐步深入每个核心概念与功能模块。通过详尽的讲解与实战演示,帮助大家掌握 Vue 3 的基础与进阶知识,最终具备独立搭建完整 Vue 3 项目的能力。
Vue 3 提供了多种方式来进行组件之间的通信。根据场景的不同,开发者可以选择最合适的方式进行数据的传递与事件的处理。
父组件:
<template>
<ChildComponent :message="parentMessage" />
</template>
<script setup>
import ChildComponent from './ChildComponent.vue';
const parentMessage = 'Hello from Parent';
</script>
子组件:
<template>
//写法1
<p>{{ message }}</p>
//写法2
<p>{{ props.message }}</p>
</template>
<script setup>
//写法1
defineProps({
message: String
});
//写法2
const props=defineProps({
message: String
});
</script>
子组件可以通过 emit 函数向父组件传递事件。不过写法和vue2有点不一样。
子组件:
<template>
<button @click="sendMessage">Send Message</button>
</template>
<script setup>
//创建一个emit,
//defineEmits数组内包含的是传给父组件的方法,多个的话以逗号隔开,
// 例子: defineEmits(['message','xxx']);
const emit = defineEmits(['message']);
const sendMessage = () => {
//使用emit像父组件传值,message为方法名,逗号后面为传递的值
//如果是定义的值直接写入就行,这里例子使用的是一个字符串
emit('message', 'Hello from Child');
}
</script>
父组件:
<template>
//和vue2一样的写法
<ChildComponent @message="handleMessage" />
</template>
<script setup>
import ChildComponent from './ChildComponent.vue';
const handleMessage = (msg) => {
console.log(msg);
}
</script>
通过 provide 和 inject,我们可以在兄弟组件之间实现数据共享。
在父先组件中使用 provide: 提供数据或方法。
父组件:
<template>
<div>
<ChildComponentA />
<ChildComponentB />
</div>
</template>
<script setup>
import { ref, provide } from 'vue';
import ChildComponentA from './ChildComponentA.vue';
import ChildComponentB from './ChildComponentB.vue';
const sharedData = ref('Hello from Parent');
provide('sharedData', sharedData);
function updateData(newData) {
sharedData.value = newData;
}
provide('updateData', updateData);
</script>
</script>
子组件A:
<template>
<div>
<p>Data: {{ sharedData }}</p>
<button @click="changeData">Change Data</button>
</div>
</template>
<script setup>
import { inject } from 'vue';
const sharedData = inject('sharedData');
const updateData = inject('updateData');
function changeData() {
updateData('Data changed by Component A');
}
</script>
子组件B:
<template>
<div>
<p>Data: {{ sharedData }}</p>
</div>
</template>
<script setup>
import { inject } from 'vue';
const sharedData = inject('sharedData');
</script>
原理:
简单的数据传递可以考虑这种方式,如果是复杂的还是选择Pinia吧,后面会有一篇专门讲解Pinia的文章,感兴趣的小伙伴可以去点评一下哦~
在复杂场景中,使用 Pinia 或 Vuex 可以更高效地进行全局状态管理。
定义 store:
import { defineStore } from 'pinia';
export const useStore = defineStore('main', {
state: () => ({
count: 0
}),
actions: {
increment() {
this.count++;
}
}
});
在组件中使用 Pinia:
<template>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
</template>
<script setup>
import { useStore } from './store';
const store = useStore();
const { count, increment } = store;
</script>
ref 可以用来获取子组件实例或 DOM 节点,并直接调用子组件方法。用法和vue2差不多,只是写法有一些变化
父组件:
<template>
<ChildComponent ref="childRef" />
<button @click="callChildMethod">Call Child Method</button>
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const childRef = ref(null);
const callChildMethod = () => {
childRef.value.someMethod();
}
</script>
子组件:
<script setup>
const someMethod = () => {
console.log('Child method called');
}
</script>
自定义事件和 v-model 结合使用可以实现组件的双向绑定。这个功能允许你在父组件和子组件之间同步数据。
父组件:
<template>
<div>
<h1>Parent Component</h1>
<ChildComponent v-model="parentData" />
<p>Parent Data: {{ parentData }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const parentData = ref('Initial data');
</script>
子组件:
<template>
<div>
<input :value="modelValue" @input="onInputChange" />
</div>
</template>
<script setup>
import { defineEmits, defineProps } from 'vue';
// 定义接收的 props
const props = defineProps({
modelValue: String
});
// 定义 emit 事件
const emit = defineEmits(['update:modelValue']);
const onInputChange = (event) => {
emit('update:modelValue', event.target.value);
};
</script>
原理:
自定义属性名
可以自定义 v-model 的属性名。例如,如果想用 value 和 input 代替 modelValue 和 update:modelValue:
子组件:
<template>
<div>
<input :value="value" @input="onInputChange" />
</div>
</template>
<script setup>
import { defineEmits, defineProps } from 'vue';
// 定义接收的 props
const props = defineProps({
value: String
});
// 定义 emit 事件
const emit = defineEmits(['input']);
const onInputChange = (event) => {
emit('input', event.target.value);
};
</script>
父组件:
<template>
<div>
<h1>Parent Component</h1>
<ChildComponent v-model:value="parentData" />
<p>Parent Data: {{ parentData }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const parentData = ref('Initial data');
</script>
在 Vue 3 中,组件通信是构建动态、交互式应用的核心。了解并掌握不同的组件通信方式能帮助我们更高效地管理数据流动和事件处理。
每种通信方式都有其适用场景,选择合适的方式能够提高应用的可维护性和可扩展性。在实际开发中,根据应用需求灵活运用这些方式,能有效提升开发效率和代码质量。