Vue3 Composition API 实战:从 setup 函数到项目全流程落地

Vue3 的 Composition API 是一种现代化的代码组织方式,它通过 setup 函数让组件逻辑更灵活、可复用。本指南将一步步带你从基础概念到实际项目落地,包括代码示例和最佳实践。内容基于 Vue3 官方文档和社区经验,确保真实可靠。我们将使用一个简单的计数器应用作为案例,逐步扩展到全流程项目。

1. 理解 Composition API 和 setup 函数

Composition API 的核心是使用函数式编程来管理组件状态和逻辑,取代 Vue2 的 Options API。setup 函数是入口点,它在组件创建前执行,用于定义响应式数据、计算属性、方法等。

  • 为什么使用:提高代码可读性、复用性和测试性,尤其适合复杂组件。
  • 基本结构
    import { ref } from 'vue';
    
    export default {
      setup() {
        // 定义响应式数据
        const count = ref(0);
        
        // 定义方法
        const increment = () => {
          count.value++;
        };
    
        // 返回数据和方法,供模板使用
        return {
          count,
          increment
        };
      }
    };
    

    这里,ref 用于创建响应式引用对象,count.value 访问值。
2. 核心响应式工具:ref、reactive、computed 和 watch

Composition API 提供多个函数来处理状态:

  • ref:用于基本类型(如数字、字符串),通过 .value 访问。
  • reactive:用于对象类型,直接修改属性即可响应。
  • computed:创建计算属性,依赖其他响应式数据。
  • watch:监听数据变化,执行副作用。

示例:计数器应用增强版

import { ref, reactive, computed, watch } from 'vue';

export default {
  setup() {
    // 使用 ref 管理基础状态
    const count = ref(0);
    
    // 使用 reactive 管理对象状态
    const user = reactive({ name: '张三', age: 25 });
    
    // 使用 computed 计算属性
    const doubleCount = computed(() => count.value * 2);
    
    // 使用 watch 监听变化
    watch(count, (newValue, oldValue) => {
      console.log(`Count changed from ${oldValue} to ${newValue}`);
    });
    
    // 方法定义
    const increment = () => count.value++;
    const updateUser = () => {
      user.age++; // 直接修改,无需 .value
    };
    
    return {
      count,
      user,
      doubleCount,
      increment,
      updateUser
    };
  }
};

3. 项目实战:构建一个简单计数器组件

现在,我们将上述代码整合到实际组件中,并添加模板。

  • 步骤
    1. 创建 Vue 组件文件(如 Counter.vue)。
    2. setup 中定义逻辑。
    3. 在模板中绑定数据和方法。

完整组件代码

<template>
  <div>
    <h1>计数器应用</h1>
    <p>当前计数: {{ count }}</p>
    <p>双倍计数: {{ doubleCount }}</p>
    <p>用户信息: {{ user.name }} - {{ user.age }}岁</p>
    <button @click="increment">增加计数</button>
    <button @click="updateUser">更新用户年龄</button>
  </div>
</template>

<script>
import { ref, reactive, computed } from 'vue';

export default {
  setup() {
    const count = ref(0);
    const user = reactive({ name: '张三', age: 25 });
    const doubleCount = computed(() => count.value * 2);
    
    const increment = () => {
      count.value++;
    };
    
    const updateUser = () => {
      user.age++;
    };
    
    return {
      count,
      user,
      doubleCount,
      increment,
      updateUser
    };
  }
};
</script>

4. 全流程项目落地:从零到部署

扩展到完整项目,涉及路由、状态管理、API 调用等。我们将使用 Vue Router 和 Pinia(Vue 官方状态管理库)。

  • 项目结构

    my-vue-project/
    ├── src/
    │   ├── components/    # 可复用组件
    │   ├── views/         # 页面组件
    │   ├── store/         # Pinia 状态管理
    │   ├── router/        # Vue Router 配置
    │   ├── App.vue        # 根组件
    │   └── main.js        # 入口文件
    ├── public/
    └── package.json
    

  • 关键步骤

    • 步骤 1: 初始化项目 使用 Vue CLI 或 Vite 创建项目:

      npm create vue@latest
      

      选择 Composition API 和相关插件。

    • 步骤 2: 集成 Vue Router 和 Pinia 安装依赖:

      npm install vue-router pinia
      

      配置路由 (src/router/index.js):

      import { createRouter, createWebHistory } from 'vue-router';
      import Home from '../views/Home.vue';
      
      const routes = [
        { path: '/', component: Home }
      ];
      
      const router = createRouter({
        history: createWebHistory(),
        routes
      });
      
      export default router;
      

      配置 Pinia 状态管理 (src/store/counterStore.js):

      import { defineStore } from 'pinia';
      
      export const useCounterStore = defineStore('counter', {
        state: () => ({ count: 0 }),
        actions: {
          increment() {
            this.count++;
          }
        }
      });
      

    • 步骤 3: 在组件中使用全局状态 修改 Home.vue 视图:

      <template>
        <div>
          <h1>首页</h1>
          <p>全局计数: {{ counterStore.count }}</p>
          <button @click="counterStore.increment">增加全局计数</button>
        </div>
      </template>
      
      <script>
      import { useCounterStore } from '@/store/counterStore';
      
      export default {
        setup() {
          const counterStore = useCounterStore();
          return { counterStore };
        }
      };
      </script>
      

    • 步骤 4: API 调用和异步处理 使用 onMountedref 处理异步数据:

      <script>
      import { ref, onMounted } from 'vue';
      import axios from 'axios';
      
      export default {
        setup() {
          const posts = ref([]);
          const loading = ref(true);
          
          onMounted(async () => {
            try {
              const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
              posts.value = response.data;
              loading.value = false;
            } catch (error) {
              console.error('API 错误:', error);
              loading.value = false;
            }
          });
          
          return { posts, loading };
        }
      };
      </script>
      

    • 步骤 5: 构建和部署 运行构建命令:

      npm run build
      

      部署到静态托管服务(如 Vercel 或 Netlify)。

5. 最佳实践和常见问题
  • 代码复用:使用自定义 hooks(如 useFetch 函数)封装逻辑。
  • 性能优化:避免不必要的重新渲染,用 shallowRefmarkRaw 处理大型对象。
  • 测试:使用 Vitest 测试组件逻辑。
  • 常见错误
    • 忘记 .value 访问 ref 数据。
    • setup 中直接修改 props;使用 toRefs 解构 props。
总结

通过本指南,你已掌握了从 setup 函数基础到项目全流程的 Vue3 Composition API 实战。关键是通过模块化代码提高可维护性,例如使用 Pinia 管理全局状态。现在,动手实践一个真实项目(如 TODO 应用或博客系统),以巩固技能。遇到问题时,查阅 Vue 官方文档 或社区资源。Happy coding!

Vue3 Composition API 实战:从 setup 函数到项目全流程落地

Vue3 的 Composition API 是一种现代化的代码组织方式,它通过 setup 函数让组件逻辑更灵活、可复用。本指南将一步步带你从基础概念到实际项目落地,包括代码示例和最佳实践。内容基于 Vue3 官方文档和社区经验,确保真实可靠。我们将使用一个简单的计数器应用作为案例,逐步扩展到全流程项目。

1. 理解 Composition API 和 setup 函数

Composition API 的核心是使用函数式编程来管理组件状态和逻辑,取代 Vue2 的 Options API。setup 函数是入口点,它在组件创建前执行,用于定义响应式数据、计算属性、方法等。

  • 为什么使用:提高代码可读性、复用性和测试性,尤其适合复杂组件。
  • 基本结构
    import { ref } from 'vue';
    
    export default {
      setup() {
        // 定义响应式数据
        const count = ref(0);
        
        // 定义方法
        const increment = () => {
          count.value++;
        };
    
        // 返回数据和方法,供模板使用
        return {
          count,
          increment
        };
      }
    };
    

    这里,ref 用于创建响应式引用对象,count.value 访问值。
2. 核心响应式工具:ref、reactive、computed 和 watch

Composition API 提供多个函数来处理状态:

  • ref:用于基本类型(如数字、字符串),通过 .value 访问。
  • reactive:用于对象类型,直接修改属性即可响应。
  • computed:创建计算属性,依赖其他响应式数据。
  • watch:监听数据变化,执行副作用。

示例:计数器应用增强版

import { ref, reactive, computed, watch } from 'vue';

export default {
  setup() {
    // 使用 ref 管理基础状态
    const count = ref(0);
    
    // 使用 reactive 管理对象状态
    const user = reactive({ name: '张三', age: 25 });
    
    // 使用 computed 计算属性
    const doubleCount = computed(() => count.value * 2);
    
    // 使用 watch 监听变化
    watch(count, (newValue, oldValue) => {
      console.log(`Count changed from ${oldValue} to ${newValue}`);
    });
    
    // 方法定义
    const increment = () => count.value++;
    const updateUser = () => {
      user.age++; // 直接修改,无需 .value
    };
    
    return {
      count,
      user,
      doubleCount,
      increment,
      updateUser
    };
  }
};

3. 项目实战:构建一个简单计数器组件

现在,我们将上述代码整合到实际组件中,并添加模板。

  • 步骤
    1. 创建 Vue 组件文件(如 Counter.vue)。
    2. setup 中定义逻辑。
    3. 在模板中绑定数据和方法。

完整组件代码

<template>
  <div>
    <h1>计数器应用</h1>
    <p>当前计数: {{ count }}</p>
    <p>双倍计数: {{ doubleCount }}</p>
    <p>用户信息: {{ user.name }} - {{ user.age }}岁</p>
    <button @click="increment">增加计数</button>
    <button @click="updateUser">更新用户年龄</button>
  </div>
</template>

<script>
import { ref, reactive, computed } from 'vue';

export default {
  setup() {
    const count = ref(0);
    const user = reactive({ name: '张三', age: 25 });
    const doubleCount = computed(() => count.value * 2);
    
    const increment = () => {
      count.value++;
    };
    
    const updateUser = () => {
      user.age++;
    };
    
    return {
      count,
      user,
      doubleCount,
      increment,
      updateUser
    };
  }
};
</script>

4. 全流程项目落地:从零到部署

扩展到完整项目,涉及路由、状态管理、API 调用等。我们将使用 Vue Router 和 Pinia(Vue 官方状态管理库)。

  • 项目结构

    my-vue-project/
    ├── src/
    │   ├── components/    # 可复用组件
    │   ├── views/         # 页面组件
    │   ├── store/         # Pinia 状态管理
    │   ├── router/        # Vue Router 配置
    │   ├── App.vue        # 根组件
    │   └── main.js        # 入口文件
    ├── public/
    └── package.json
    

  • 关键步骤

    • 步骤 1: 初始化项目 使用 Vue CLI 或 Vite 创建项目:

      npm create vue@latest
      

      选择 Composition API 和相关插件。

    • 步骤 2: 集成 Vue Router 和 Pinia 安装依赖:

      npm install vue-router pinia
      

      配置路由 (src/router/index.js):

      import { createRouter, createWebHistory } from 'vue-router';
      import Home from '../views/Home.vue';
      
      const routes = [
        { path: '/', component: Home }
      ];
      
      const router = createRouter({
        history: createWebHistory(),
        routes
      });
      
      export default router;
      

      配置 Pinia 状态管理 (src/store/counterStore.js):

      import { defineStore } from 'pinia';
      
      export const useCounterStore = defineStore('counter', {
        state: () => ({ count: 0 }),
        actions: {
          increment() {
            this.count++;
          }
        }
      });
      

    • 步骤 3: 在组件中使用全局状态 修改 Home.vue 视图:

      <template>
        <div>
          <h1>首页</h1>
          <p>全局计数: {{ counterStore.count }}</p>
          <button @click="counterStore.increment">增加全局计数</button>
        </div>
      </template>
      
      <script>
      import { useCounterStore } from '@/store/counterStore';
      
      export default {
        setup() {
          const counterStore = useCounterStore();
          return { counterStore };
        }
      };
      </script>
      

    • 步骤 4: API 调用和异步处理 使用 onMountedref 处理异步数据:

      <script>
      import { ref, onMounted } from 'vue';
      import axios from 'axios';
      
      export default {
        setup() {
          const posts = ref([]);
          const loading = ref(true);
          
          onMounted(async () => {
            try {
              const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
              posts.value = response.data;
              loading.value = false;
            } catch (error) {
              console.error('API 错误:', error);
              loading.value = false;
            }
          });
          
          return { posts, loading };
        }
      };
      </script>
      

    • 步骤 5: 构建和部署 运行构建命令:

      npm run build
      

      部署到静态托管服务(如 Vercel 或 Netlify)。

5. 最佳实践和常见问题
  • 代码复用:使用自定义 hooks(如 useFetch 函数)封装逻辑。
  • 性能优化:避免不必要的重新渲染,用 shallowRefmarkRaw 处理大型对象。
  • 测试:使用 Vitest 测试组件逻辑。
  • 常见错误
    • 忘记 .value 访问 ref 数据。
    • setup 中直接修改 props;使用 toRefs 解构 props。
总结

通过本指南,你已掌握了从 setup 函数基础到项目全流程的 Vue3 Composition API 实战。关键是通过模块化代码提高可维护性,例如使用 Pinia 管理全局状态。现在,动手实践一个真实项目(如 TODO 应用或博客系统),以巩固技能。遇到问题时,查阅 Vue 官方文档 或社区资源。Happy coding!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐