【前端】Vue 3 Composition API 核心工具详解:从 ref到生命周期钩子

发布于:2025-07-19 ⋅ 阅读:(21) ⋅ 点赞:(0)


一、引言:为什么需要 Composition API?

在 Vue 2 的 Options API 中,开发者通过 datamethodscomputed 等选项组织代码。虽然逻辑清晰,但随着组件复杂度增加,跨选项的逻辑复用变得困难(例如,一个功能可能同时需要修改 data、调用 methods 和监听生命周期)。Vue 3 引入的 Composition API 通过函数式编程解决了这一问题,允许将相关逻辑聚合在一起,提升代码的可维护性和复用性。

本文将深入解析 Composition API 的四大核心工具:refcomputedonMountedonBeforeMount,并通过代码示例展示它们的实际应用场景。


二、ref:响应式状态的基石

2.1 什么是 ref

ref 是 Vue 3 中创建响应式引用的核心 API。它可以包装任何类型的值(基本类型或对象),并返回一个带有 .value 属性的响应式对象。在模板中,Vue 会自动解包 .value,开发者无需手动访问。

2.2 基本用法

import { ref } from 'vue';

const count = ref(0); // 包装数字
const message = ref('Hello Vue 3'); // 包装字符串
const user = ref({ name: 'Alice' }); // 包装对象

// 访问值需通过 .value
console.log(count.value); // 0
count.value++; // 修改值

2.3 模板中的自动解包

在模板中直接使用 ref 变量,无需 .value

<template>
  <div>
    <p>{{ count }}</p> <!-- 自动解包为 0 -->
    <button @click="count++">Increment</button>
  </div>
</template>

2.4 为什么需要 ref

  • 响应式更新:当 .value 变化时,依赖它的组件会自动重新渲染。
  • 类型安全:与 Vue 2 的 this.$data 不同,ref 在 TypeScript 中能提供更好的类型推断。
  • 灵活性:可以包装任何值,包括对象、数组甚至函数。

2.5 注意事项

  • 对象引用:直接替换整个对象时需重新赋值(如 user.value = { name: 'Bob' }),而非修改内部属性(如 user.value.name = 'Bob' 也能触发响应,但推荐前者以保持一致性)。
  • 避免滥用:对于简单组件,Options API 可能更简洁;ref 更适合复杂逻辑或需要复用的场景。

三、computed:派生状态的优化器

3.1 什么是 computed

computed 用于创建计算属性,基于其他响应式数据派生新值。它会自动缓存结果,只有依赖变化时才重新计算,避免不必要的开销。

3.2 基本用法

import { ref, computed } from 'vue';

const count = ref(0);
const doubleCount = computed(() => count.value * 2); // 依赖 count

console.log(doubleCount.value); // 0
count.value = 3;
console.log(doubleCount.value); // 6(自动更新)

3.3 可写计算属性

默认情况下,computed 是只读的。若需可写,可以传入一个带有 getset 的对象:

const fullName = computed({
  get: () => `${firstName.value} ${lastName.value}`,
  set: (newValue) => {
    const [first, last] = newValue.split(' ');
    firstName.value = first;
    lastName.value = last;
  }
});

3.4 与 ref + 方法对比

  • 方法:每次调用都会重新计算,无缓存。
    const getDoubleCount = () => count.value * 2; // 每次调用都计算
    
  • 计算属性:仅依赖变化时重新计算,适合频繁使用的派生值。

3.5 适用场景

  • 复杂计算(如过滤列表、格式化数据)。
  • 需要缓存的派生状态(如表单验证结果)。
  • v-model 结合实现双向绑定。

四、生命周期钩子:掌控组件时序

4.1 为什么需要生命周期钩子?

组件从创建到销毁会经历多个阶段(如初始化、挂载、更新、卸载)。生命周期钩子允许开发者在特定时机执行逻辑(如 API 调用、DOM 操作)。

4.2 onBeforeMount:挂载前的最后准备

  • 触发时机:在组件完成模板编译,但尚未渲染到 DOM 之前调用。
  • 典型用途
    • 读取最终 DOM 尺寸(需等待渲染,通常用 onMounted 更合适)。
    • 初始化非响应式第三方库(如图表库)。
import { onBeforeMount } from 'vue';

onBeforeMount(() => {
  console.log('组件即将挂载,DOM 未就绪');
});

4.3 onMounted:DOM 就绪的信号

  • 触发时机:组件挂载到 DOM 后立即调用。
  • 典型用途
    • 执行 API 请求。
    • 操作 DOM(如聚焦输入框)。
    • 启动定时器或事件监听。
import { onMounted, ref } from 'vue';

const data = ref(null);

onMounted(async () => {
  const response = await fetch('/api/data');
  data.value = await response.json();
});

4.4 其他常用钩子

  • onBeforeUpdate / onUpdated:响应式数据变化时触发。
  • onUnmounted:组件卸载时清理资源(如取消订阅、清除定时器)。

4.5 对比 Options API

Composition API Options API
onMounted(() => {}) mounted() {}
onBeforeMount(() => {}) beforeMount() {}

Composition API 的钩子通过函数调用注册,更灵活且易于提取逻辑。


五、实战案例:组合使用 refcomputed 和生命周期钩子

5.1 场景:用户列表展示与搜索

import { ref, computed, onMounted } from 'vue';

export default {
  setup() {
    // 响应式状态
    const users = ref([]);
    const searchQuery = ref('');
    const isLoading = ref(false);

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

    // 生命周期钩子:加载数据
    onMounted(async () => {
      isLoading.value = true;
      try {
        const response = await fetch('https://api.example.com/users');
        users.value = await response.json();
      } finally {
        isLoading.value = false;
      }
    });

    // 返回模板可用的变量和方法
    return {
      users: filteredUsers, // 暴露计算属性而非原始数据
      searchQuery,
      isLoading
    };
  }
};

5.2 模板部分

<template>
  <div>
    <input v-model="searchQuery" placeholder="搜索用户..." />
    <div v-if="isLoading">加载中...</div>
    <ul v-else>
      <li v-for="user in users" :key="user.id">
        {{ user.name }}
      </li>
    </ul>
  </div>
</template>

5.3 代码解析

  1. ref:管理 userssearchQueryisLoading 的状态。
  2. computed:根据 searchQuery 实时过滤用户列表。
  3. onMounted:组件挂载后自动加载数据,并处理加载状态。

6、总结与展望

6.1 核心工具回顾

  • ref:创建响应式状态。
  • computed:缓存派生状态。
  • onMounted / onBeforeMount:控制组件生命周期。

6.2 Composition API 的优势

  • 逻辑复用:通过自定义组合式函数(Composables)提取公共逻辑。
  • 更好的 TypeScript 支持:明确的类型推断和接口定义。
  • 更灵活的代码组织:按功能而非选项划分代码。

6.3 进一步学习建议

  • 探索 watchwatchEffect:处理异步依赖和副作用。
  • 学习 provide / inject:实现跨组件通信。
  • 尝试 Pinia:基于 Composition API 的状态管理库。

Vue 3 的 Composition API 为前端开发带来了更现代化的编程范式。通过掌握 refcomputed 和生命周期钩子,你可以更高效地构建复杂应用,同时保持代码的清晰和可维护性。


网站公告

今日签到

点亮在社区的每一天
去签到