在前面的课程里,我们已经多次使用了组合式API。组合式API是Vue 3的重要特性,它提供了更好的逻辑复用和代码组织方式。这一节课,我们将深入学习组合式API的高级特性,包括setup函数的深入理解、组合式函数(composables)的创建和使用、响应式工具函数等。
掌握组合式API的高级特性,可以帮助我们写出更加模块化、可复用和易维护的代码。这些知识是构建大型Vue应用的基础。

setup函数是组合式API的核心,在每个组件实例被创建之前执行。该函数会被Vue在初始化组件时调用,并允许你用组合式API来构建组件的逻辑。在setup中,我们可以访问两个参数:
props:组件传入的属性对象,是响应式的,可以直接通过props.xxx访问父组件传递进来的数据。注意直接解构props会丢失响应性,如果确实需要分解,可以使用Vue的toRefs工具。context:上下文对象,包含了attrs(除props外传入的属性和事件监听器)、slots(插槽内容)、emit(自定义事件触发方法)等。这些可以帮助我们在setup中与外部进行交互。<div id="app">
<user-card name="张三" :age="25"></user-card>
</div>
<script>
const { createApp } = Vue;
const UserCard = {
props: {
name: String,
age: Number
},
setup(props) {
// props是响应式的,但不要解构它
console.log('name:', props.name);
console.log('age:', props.age);
// 如果需要解构,使用toRefs
const { toRefs } = Vue;
const { name, age } = toRefs(props);
return {
name,
age
};
},
template: `
<div>
<h3>{{ name }}</h3>
<p>年龄:{{ age }}</p>
</div>
`
};
const app = createApp({});
app.component('user-card', UserCard);
app.mount('#app');
</script>在这个例子中,setup函数接收props参数。注意,props是响应式的,但如果我们直接解构它,会失去响应性。如果需要解构,应该使用toRefs。
context参数包含了组件的上下文信息:
<div id="app">
<child-component @custom-event="handleEvent"></child-component>
</div>
<script>
const { createApp } = Vue;
const ChildComponent = {
setup(props, context) {
// context.attrs: 包含所有非props的属性
console.
context对象包含四个属性:attrs、slots、emit和expose。我们可以使用解构来获取这些属性,例如:
<script>
const ChildComponent = {
setup(props, { attrs, slots, emit, expose }) {
// 使用解构的方式
emit('custom-event', '数据');
return {};
}
};
</script>组合式函数(Composables)是指利用 Vue 3 组合式 API(如 ref、reactive、computed、watch 等)编写的可复用函数。它们能够将组件内部可复用的状态逻辑进行封装和抽离,方便在多个组件中共享和复用。
组合式函数的命名通常以 use 开头,例如 useCounter、useFetch 等。开发者可以在组合式函数中封装数据状态、方法、计算属性甚至副作用逻辑,然后通过 return 暴露需要在组件中使用的内容,从而提升逻辑复用性和代码组织性。
让我们创建一个简单的组合式函数:
<div id="app">
<counter-component></counter-component>
<counter-component></counter-component>
</div>
<script>
const { createApp, ref } = Vue;
// 创建一个组合式函数
function useCounter(initialValue = 0) {
const
在这个例子中,我们创建了一个useCounter组合式函数,它封装了计数器的逻辑。多个组件可以复用这个函数,每个组件都有自己独立的计数器状态。
有时候,我们需要在组合式函数中处理异步操作(比如调用接口获取数据)。此时,可以将组合式函数写为异步函数,并在其中封装 API 请求的逻辑。这样设计后,多个组件可以方便地复用同一套异步数据获取与状态管理流程。例如:
<div id="app">
<user-profile></user-profile>
</div>
<script>
const { createApp, ref } = Vue;
// 异步组合式函数
async function useUser(userId) {
const user = ref(null);
在这个例子中,我们创建了一个异步的useUser组合式函数,它用于获取用户数据。注意,setup函数也可以是异步的。
Vue提供了一些工具函数来处理响应式数据。让我们看看常用的工具函数:
toRef和toRefs是Vue 3中用于与响应式对象密切配合的重要工具函数。它们的作用是将响应式对象(如由reactive创建的对象)中的属性“包装”为ref响应式引用,从而可以单独使用这些属性并保持响应性。
toRef(obj, key):将响应式对象obj的某个属性key转换为一个ref,这样就可以独立地对这个属性进行响应式追踪。如果直接解构reactive对象,属性会失去响应性,而使用toRef可以避免这个问题。toRefs(obj):将整个响应式对象的每个属性都一次性转换为ref,返回的是一个包含所有ref属性的新对象。这样可以使用对象解构赋值,且不会丢失响应性。这两个函数主要用于在解构reactive对象、或将部分属性单独传递到子组件时,确保属性依然具有响应式更新能力。
<div id="app">
<component-a></component-a>
</div>
<script>
const { createApp, reactive, toRef, toRefs } = Vue;
const ComponentA = {
setup() {
const state = reactive
unref 和 isRef 是 Vue 3 Composition API 中常用的工具函数,用于更灵活地处理响应式数据。
unref(value):用于安全地获取ref的“真实”值。如果传入的是一个ref对象,它会返回其.value属性;如果传入的本身不是ref(比如普通的变量或响应式对象属性),则直接返回该值本身。因此,可以统一处理“可能是ref也可能不是ref”的场景,无需判断类型。例如:
unref(refVar) 返回的是 refVar.valueunref(普通变量) 返回的是该变量的值isRef(value):用于判断某个变量是否为ref对象(即由ref()或computed()等API创建的响应式引用)。返回布尔值,只有传入的确实是ref时才为true,否则为false。
这两个函数可以让你在写通用组件或工具函数时,更加方便地处理混杂ref与普通变量的情况。
<div id="app">
<component-b></component-b>
</div>
<script>
const { createApp, ref, unref, isRef } = Vue;
const ComponentB = {
setup() {
const count = ref(
readonly 是 Vue 提供的一个响应式 API,用于基于现有响应式对象创建一个“只读版本”。通过 readonly 包裹之后,返回的新对象本身依然具备响应性(可以在模板或其他代码中使用),但它的属性不允许被修改,任何试图通过只读对象修改属性的操作都会失效,在开发模式下还会报出警告。
这通常用于防止数据被意外更改,尤其是在需要将响应式数据安全地传递到子组件、插件或外部函数时。例如,如果你将一个响应式对象通过 readonly 包裹后传递给子组件,子组件只能读取其内容,而无法修改数据本身,从而保证了数据的不可变性和代码的稳定。
<div id="app">
<component-c></component-c>
</div>
<script>
const { createApp, reactive, readonly } = Vue;
const ComponentC = {
setup() {
const state = reactive({
count:
接下来,我们将详细创建一个完整的组合式函数(Composable),用于管理待办事项(Todo List),涵盖添加、删除、切换完成状态、清除已完成、以及统计数据等常见功能。这个函数将能帮助你在任意组件中轻松复用待办事项的核心逻辑,并保持状态响应式与解耦。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组合式API深入示例</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
在这个例子中,我们创建了一个完整的useTodos组合式函数,它封装了所有待办事项相关的逻辑。这个函数可以在多个组件中复用,每个组件都有自己独立的待办事项列表。
在这一节中,我们深入学习了组合式API的高级特性。我们了解了setup函数的深入用法,学习了如何创建和使用组合式函数,以及如何使用响应式工具函数。 组合式API提供了更好的逻辑复用和代码组织方式。通过组合式函数,我们可以将逻辑封装成可复用的单元,让代码更加模块化和易维护。
在下一个部分中,我们将学习Vue Router,了解如何在Vue应用中实现路由功能。这将是我们构建单页应用(SPA)必不可少的一部分。