Vue 3 Composition API深度解析:从Options API到现代组件开发

引言:Vue 3的革命性变化

Vue 3带来了许多令人兴奋的新特性,其中最引人注目的就是Composition API。这个新的API设计彻底改变了我们编写Vue组件的方式,提供了更好的代码组织、类型支持和逻辑复用能力。

1. Options API vs Composition API

首先,让我们对比一下传统的Options API和新的Composition API。

Options API(传统方式)

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
    <p>Double: {{ doubleCount }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 0
    };
  },
  computed: {
    doubleCount() {
      return this.count * 2;
    }
  },
  methods: {
    increment() {
      this.count++;
    }
  },
  mounted() {
    console.log("Component mounted");
  }
};
</script>

Composition API(现代方式)

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
    <p>Double: {{ doubleCount }}</p>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from "vue";

// 响应式状态
const count = ref(0);

// 计算属性
const doubleCount = computed(() => count.value * 2);

// 方法
function increment() {
  count.value++;
}

// 生命周期钩子
onMounted(() => {
  console.log("Component mounted");
});
</script>

2. Composition API核心概念

2.1 ref和reactive

ref和reactive是创建响应式数据的两种主要方式。

import { ref, reactive } from "vue";

// ref用于基本类型
const count = ref(0);
const message = ref("Hello Vue 3");

// reactive用于对象
const user = reactive({
  name: "张三",
  age: 25,
  email: "zhangsan@example.com"
});

// 访问ref的值需要使用.value
console.log(count.value); // 0
count.value = 1; // 更新值

// reactive对象可以直接访问
console.log(user.name); // 张三
user.age = 26; // 直接更新

2.2 computed和watch

import { ref, computed, watch } from "vue";

const price = ref(100);
const quantity = ref(2);

// 计算属性
tconst total = computed(() => price.value * quantity.value);

// 监听器
watch(quantity, (newValue, oldValue) => {
  console.log(`数量从 ${oldValue} 变为 ${newValue}`);
  console.log(`新的总价: ${total.value}`);
});

// 监听多个源
watch([price, quantity], ([newPrice, newQuantity], [oldPrice, oldQuantity]) => {
  console.log(`价格或数量发生变化`);
});

3. 逻辑复用:Composables

Composition API最大的优势之一是逻辑复用。我们可以创建可复用的composable函数。

// useCounter.js - 可复用的计数器逻辑
export function useCounter(initialValue = 0) {
  const count = ref(initialValue);
  
  const increment = () => {
    count.value++;
  };
  
  const decrement = () => {
    count.value--;
  };
  
  const reset = () => {
    count.value = initialValue;
  };
  
  const double = computed(() => count.value * 2);
  
  return {
    count,
    increment,
    decrement,
    reset,
    double
  };
}

// 在组件中使用
<script setup>
import { useCounter } from "./useCounter";

const { count, increment, double } = useCounter(10);
</script>

4. 实际应用:用户管理组件

让我们创建一个实际的用户管理组件,展示Composition API的强大功能。

<template>
  <div>
    <h2>用户管理</h2>
    
    <div v-if="loading">加载中...</div>
    
    <div v-else>
      <input 
        v-model="searchQuery" 
        placeholder="搜索用户" 
        @input="searchUsers"
      />
      
      <ul>
        <li v-for="user in filteredUsers" :key="user.id">
          {{ user.name }} - {{ user.email }}
          <button @click="() => selectUser(user)">选择</button>
        </li>
      </ul>
      
      <div v-if="selectedUser">
        <h3>已选择: {{ selectedUser.name }}</h3>
        <button @click="clearSelection">清除选择</button>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from "vue";

// 响应式状态
const users = ref([]);
const loading = ref(true);
const searchQuery = ref("");
const selectedUser = ref(null);

// 计算属性:过滤用户
const filteredUsers = computed(() => {
  if (!searchQuery.value) return users.value;
  
  return users.value.filter(user => 
    user.name.toLowerCase().includes(searchQuery.value.toLowerCase()) ||
    user.email.toLowerCase().includes(searchQuery.value.toLowerCase())
  );
});

// 方法
async function fetchUsers() {
  try {
    loading.value = true;
    // 模拟API调用
    const response = await fetch("https://api.example.com/users");
    users.value = await response.json();
  } catch (error) {
    console.error("获取用户失败:", error);
  } finally {
    loading.value = false;
  }
}

function searchUsers() {
  // 搜索逻辑已通过计算属性处理
  console.log("搜索关键词:", searchQuery.value);
}

function selectUser(user) {
  selectedUser.value = user;
}

function clearSelection() {
  selectedUser.value = null;
}

// 生命周期钩子
onMounted(() => {
  fetchUsers();
});
</script>

5. TypeScript支持

Composition API天生对TypeScript友好,提供了更好的类型推断和类型安全。

<script setup lang="ts">
import { ref, computed } from "vue";

// 定义接口
interface User {
  id: number;
  name: string;
  email: string;
  age?: number; // 可选属性
}

// 类型化的ref
const users = ref<User[]>([]);
const selectedUserId = ref<number | null>(null);

// 类型化的计算属性
const selectedUser = computed<User | undefined>(() => {
  return users.value.find(user => user.id === selectedUserId.value);
});

// 类型化的函数
function addUser(user: User): void {
  users.value.push(user);
}

// 自动类型推断
const count = ref(0); // 推断为Ref<number>
const message = ref("Hello"); // 推断为Ref<string>
</script>

6. 最佳实践

  • 逻辑组织:将相关逻辑组织在一起,而不是按选项类型分散
  • Composables:将可复用的逻辑提取到composable函数中
  • 类型安全:使用TypeScript获得更好的开发体验
  • 响应式优化:合理使用ref和reactive,避免不必要的响应式开销
  • 代码拆分:大型组件可以拆分为多个composable函数

总结

Vue 3的Composition API代表了现代前端组件开发的未来方向。它提供了更好的代码组织、类型支持和逻辑复用能力。虽然Options API仍然可用且适合简单组件,但对于复杂应用和需要高度复用的场景,Composition API无疑是更好的选择。通过掌握Composition API,开发者可以编写更清晰、更可维护、更高效的Vue应用。

© 版权声明
THE END
喜欢就支持一下吧
点赞5 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容