Tailwind CSSTailwind CSS
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
  • 示例:用 Composition API 重构一个组件

示例:用 Composition API 重构一个组件

通过前几节的学习,你已经了解了 Composition API 的优势和基本用法。本节将通过一个实际示例,展示如何将一个使用 Options API 编写的组件重构为 Composition API 版本。你将看到逻辑如何从分散变为集中,并体会这种方式在可读性、复用性和维护性上的提升。

原始组件:Options API 版本

假设我们有一个任务管理组件,包含任务列表、筛选功能和计数器功能,使用 Options API 实现:

<!-- TaskManager.vue -->
<template>
  <div>
    <h1>任务管理</h1>
    <input v-model="newTask" placeholder="添加新任务" @keyup.enter="addTask" />
    <select v-model="filter">
      <option value="all">全部</option>
      <option value="completed">已完成</option>
      <option value="pending">未完成</option>
    </select>
    <ul>
      <li v-for="task in filteredTasks" :key="task.id" :class="{ completed: task.done }">
        <input type="checkbox" v-model="task.done" />
        {{ task.title }}
      </li>
    </ul>
    <p>任务总数:{{ taskCount }}</p>
    <p>点击次数:{{ clickCount }}</p>
    <button @click="incrementClick">点击我</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      newTask: '',
      filter: 'all',
      tasks: [
        { id: 1, title: '学习 Vue 3', done: false },
        { id: 2, title: '完成项目', done: true }
      ],
      clickCount: 0
    };
  },
  computed: {
    filteredTasks() {
      if (this.filter === 'completed') {
        return this.tasks.filter(task => task.done);
      } else if (this.filter === 'pending') {
        return this.tasks.filter(task => !task.done);
      }
      return this.tasks;
    },
    taskCount() {
      return this.tasks.length;
    }
  },
  methods: {
    addTask() {
      if (this.newTask.trim()) {
        this.tasks.push({
          id: Date.now(),
          title: this.newTask,
          done: false
        });
        this.newTask = '';
      }
    },
    incrementClick() {
      this.clickCount++;
    }
  }
};
</script>

<style scoped>
.completed {
  text-decoration: line-through;
  color: gray;
}
</style>

分析问题

  • 逻辑分散:任务相关逻辑(tasks、filteredTasks、addTask)和计数器逻辑(clickCount、incrementClick)分布在 data、computed 和 methods 中。
  • 复用性低:若需在其他组件复用计数器逻辑,只能通过 Mixin,增加了复杂性。
  • 可维护性:新增功能时,需在多个选项间跳转修改。

重构为 Composition API

我们将上述组件重构为 Composition API,将逻辑按功能模块组织,并提取可复用的部分。

重构后的代码

<!-- TaskManager.vue -->
<template>
  <div>
    <h1>任务管理</h1>
    <input v-model="taskState.newTask" placeholder="添加新任务" @keyup.enter="addTask" />
    <select v-model="filter">
      <option value="all">全部</option>
      <option value="completed">已完成</option>
      <option value="pending">未完成</option>
    </select>
    <ul>
      <li v-for="task in filteredTasks" :key="task.id" :class="{ completed: task.done }">
        <input type="checkbox" v-model="task.done" />
        {{ task.title }}
      </li>
    </ul>
    <p>任务总数:{{ taskCount }}</p>
    <p>点击次数:{{ clickCount }}</p>
    <button @click="incrementClick">点击我</button>
  </div>
</template>

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

// 提取计数器逻辑
function useCounter() {
  const clickCount = ref(0);
  const incrementClick = () => {
    clickCount.value++;
  };
  return { clickCount, incrementClick };
}

// 任务管理逻辑
function useTasks() {
  const taskState = reactive({
    newTask: '',
    tasks: [
      { id: 1, title: '学习 Vue 3', done: false },
      { id: 2, title: '完成项目', done: true }
    ]
  });
  const filter = ref('all');

  const filteredTasks = computed(() => {
    if (filter.value === 'completed') {
      return taskState.tasks.filter(task => task.done);
    } else if (filter.value === 'pending') {
      return taskState.tasks.filter(task => !task.done);
    }
    return taskState.tasks;
  });

  const taskCount = computed(() => taskState.tasks.length);

  const addTask = () => {
    if (taskState.newTask.trim()) {
      taskState.tasks.push({
        id: Date.now(),
        title: taskState.newTask,
        done: false
      });
      taskState.newTask = '';
    }
  };

  return { taskState, filter, filteredTasks, taskCount, addTask };
}

export default {
  setup() {
    const { taskState, filter, filteredTasks, taskCount, addTask } = useTasks();
    const { clickCount, incrementClick } = useCounter();

    return {
      taskState,
      filter,
      filteredTasks,
      taskCount,
      addTask,
      clickCount,
      incrementClick
    };
  }
};
</script>

<style scoped>
.completed {
  text-decoration: line-through;
  color: gray;
}
</style>

重构亮点

  1. 逻辑集中:
    • 任务相关逻辑(taskState、filteredTasks、addTask)集中在 useTasks 函数中。
    • 计数器逻辑(clickCount、incrementClick)独立为 useCounter。
  2. 可复用性:
    • useCounter 可在其他组件中直接导入复用,无命名冲突。
    <script>
    import { useCounter } from './composables/counter';
    export default {
      setup() {
        return useCounter();
      }
    };
    </script>
    
  3. 清晰性:
    • setup 只负责组合和返回逻辑,职责单一。
    • 每个函数专注于单一功能,便于调试和扩展。

重构后的改进

1. 可读性提升

  • Options API:开发者需在 data、computed 和 methods 间跳转,理解任务和计数器的关系。
  • Composition API:相关代码集中在一个函数内,一目了然。

2. 扩展性增强

添加新功能(如删除任务)只需修改 useTasks:

function useTasks() {
  // ... 现有代码 ...
  const removeTask = (taskId) => {
    taskState.tasks = taskState.tasks.filter(task => task.id !== taskId);
  };
  return { taskState, filter, filteredTasks, taskCount, addTask, removeTask };
}
  • 对比:Options API 需在 methods 中新增方法,分散性增加。

3. 类型支持

Composition API 天然支持 TypeScript:

interface Task {
  id: number;
  title: string;
  done: boolean;
}

function useTasks() {
  const taskState = reactive({
    newTask: '',
    tasks: [] as Task[]
  });
  // ... 其余逻辑 ...
}

注意事项

  1. 响应性保持:
    • 返回 taskState.tasks 而非解构 { tasks },避免丢失响应性。
  2. 函数命名:
    • 使用 useXxx 前缀,遵循社区惯例,便于识别可复用逻辑。
  3. 模块化:
    • 可将 useTasks 和 useCounter 提取到单独文件(如 composables/tasks.js),进一步分离关注点。

总结

通过将任务管理组件从 Options API 重构为 Composition API,我们实现了逻辑的集中化和复用性提升。Composition API 的函数式风格让代码更模块化、可测试,尤其适合复杂组件开发。掌握这种重构技巧后,你可以轻松应对更大规模的项目。下一章将深入高级 Composition API 特性,继续探索其强大功能!

Last Updated:: 2/24/25, 10:24 AM