Vue 3 Composition API 进阶:打造可拖拽看板应用 - 自定义 Hook 的强大复用性

引言

欢迎再次回到 Vue 3 + 现代前端工程化 系列技术博客! 在昨天的第五篇博客中,我们深入学习了 Vue 3 状态管理,构建了用户登录注册功能,并掌握了 Vuex 集中管理应用状态的核心模式。 今天,我们将继续深化 Vue 3 核心技术栈的学习,聚焦于 Composition API 的进阶应用,特别是 自定义 Hook (Custom Hooks) 的创建和复用

Vue 3 Composition API 自推出以来,便以其逻辑组织性、代码复用性和类型推导优势,受到了广大 Vue 开发者的喜爱。 它通过 setup 函数,让我们能够以更灵活、更接近逻辑关注点的方式组织组件代码。 而 自定义 Hook 则是 Composition API 的精髓所在,它允许我们将组件中可复用的逻辑代码块,抽取到独立的函数中进行封装,并在多个组件之间共享和复用,极大地提升了代码的组织性和可维护性。 在本篇博客中,我们将通过构建一个 可拖拽的看板应用,深入探索 Composition API 的进阶用法,掌握自定义 Hook 的创建和复用技巧,进一步释放 Composition API 的强大潜力。

通过这个项目,您将学习到:

  • Vue 3 Composition API 进阶: 深入理解 Composition API 的灵活性和代码复用性,解锁 Composition API 的高级用法。
  • 自定义 Hook (Custom Hooks): 掌握自定义 Hook 的定义、创建和使用方法,理解自定义 Hook 在代码复用和逻辑组织中的作用。
  • 逻辑抽取与复用: 学习如何将组件中可复用的逻辑代码块,抽取到自定义 Hook 中进行封装,并在多个组件之间共享和复用。
  • 构建可拖拽交互: 体验使用自定义 Hook 处理复杂的用户交互逻辑,例如拖拽操作,提升组件的交互性和用户体验。
  • 组件逻辑组织: 使用自定义 Hook 优化组件的代码结构,使组件逻辑更清晰、更易于理解和维护。
  • 技能跃迁: 从 Composition API 基础应用进阶到自定义 Hook 的灵活运用,提升您的 Vue 3 组件设计和代码组织能力。
  • 工程化思维: 使用自定义 Hook 提升代码复用性和可维护性,进一步提升您的前端工程化实践水平。

项目简介: 可拖拽看板应用

我们将构建一个简易的可拖拽看板应用,使其具备以下核心功能:

  • 看板列表展示: 展示多个看板列表 (例如,待办、进行中、已完成)。
  • 任务卡片: 每个看板列表包含多个任务卡片,卡片上显示任务标题。
  • 任务卡片拖拽: 用户可以拖拽任务卡片在不同的看板列表之间移动。
  • 简单的状态管理: 使用 Composition API 的响应式数据管理看板列表和任务卡片数据。 (本篇博客暂不引入 Vuex 等复杂状态管理方案,重点演示自定义 Hook 的运用)。

通过构建可拖拽看板应用,我们将深入实践:

  • 自定义 Hook 创建: 创建自定义 Hook 封装可复用的拖拽逻辑,例如 useDragAndDrop
  • Hook 复用: 在不同的看板列表组件中复用 useDragAndDrop Hook,实现任务卡片的拖拽功能。
  • Composition API 组合: 在组件中使用多个 Composition API 特性 (例如 ref, reactive, computed, watch, onMounted, 自定义 Hook) 构建复杂组件逻辑。
  • DOM 操作: 使用 Composition API 的 ref 获取 DOM 元素引用,并在自定义 Hook 中进行 DOM 操作 (例如,拖拽事件监听、样式修改)。

Vue 3 Composition API 进阶概念回顾 - 自定义 Hook 的奥秘

在深入项目实战之前,让我们回顾 Vue 3 Composition API 的进阶概念,重点理解自定义 Hook 的定义、作用和优势。

  • Composition API 的核心优势 - 逻辑复用和组织: 回顾 Composition API 的设计初衷,是为了解决 Options API 在大型组件中逻辑分散、代码复用性差等问题。 Composition API 通过 setup 函数,让我们能够以更灵活的方式组织组件逻辑,并将相关逻辑代码聚合在一起,提高了代码的可读性和可维护性。
  • 自定义 Hook (Custom Hooks) 的定义: 自定义 Hook 本质上就是一个 JavaScript 函数,它约定以 use 开头命名 (例如 useMouse, useStorage, useDragAndDrop),并在函数内部使用 Composition API 的响应式 API (例如 ref, reactive, computed, watch) 来封装 可复用的组件逻辑。 自定义 Hook 可以返回任何需要在组件中使用的响应式数据、方法或计算属性。
  • 自定义 Hook 的作用和优势:
    • 代码复用: 自定义 Hook 可以将组件中可复用的逻辑代码块抽取出来,并在多个组件之间共享和复用,避免代码重复编写,提高开发效率。
    • 逻辑组织: 自定义 Hook 可以将复杂的组件逻辑拆分成更小的、独立的逻辑单元,每个 Hook 负责一部分功能,使得组件逻辑更清晰、更易于理解和维护。
    • 提高可测试性: 自定义 Hook 是独立的 JavaScript 函数,易于进行单元测试,可以更好地保证代码质量。
    • 组件解耦: 使用自定义 Hook 可以将组件的展示逻辑和业务逻辑解耦,使得组件更加专注于 UI 渲染和用户交互,提高了组件的内聚性和可复用性。
    • 促进代码组织模式: 自定义 Hook 鼓励开发者采用 “关注点分离 (Separation of Concerns)” 的原则组织代码,将组件逻辑按功能模块划分为不同的 Hook,形成更清晰、更模块化的代码结构。

为什么自定义 Hook 如此重要?

自定义 Hook 是 Vue 3 Composition API 的核心精髓之一,它为我们带来了诸多优势,尤其是在构建大型、复杂应用时:

  • 代码复用最大化: 自定义 Hook 提供了极致的代码复用能力,可以将任何组件逻辑 (例如,数据获取、状态管理、事件处理、DOM 操作、第三方库集成等) 封装成 Hook,并在任何需要的地方轻松复用,避免重复造轮子。
  • 大型项目代码组织利器: 在大型项目中,组件逻辑往往非常复杂,使用自定义 Hook 可以将复杂组件拆分成多个小而精的 Hook,每个 Hook 负责特定逻辑,极大地提升了代码组织性和可维护性,降低了维护成本。
  • 团队协作效率提升: 自定义 Hook 使得团队成员可以并行开发不同的 Hook,并共享和复用已有的 Hook,提高了团队协作效率。 Hook 的独立性和可复用性也降低了代码冲突和沟通成本。
  • 代码可测试性增强: 自定义 Hook 是独立的 JavaScript 函数,可以独立进行单元测试,保证 Hook 的质量和稳定性。 组件只需要关注自身的 UI 渲染逻辑,降低了组件的测试难度。
  • 构建可扩展的应用: 自定义 Hook 使得应用架构更具扩展性。 当需要添加新功能或修改现有功能时,可以通过创建新的 Hook 或修改已有的 Hook 来实现,而无需修改大量的组件代码,提高了应用的灵活性和可扩展性。

实战步骤: 打造可拖拽看板应用

接下来,我们将一步步使用 Vue 3 Composition API 和自定义 Hook 构建我们的可拖拽看板应用,深入理解自定义 Hook 的创建和复用。

步骤 1: 项目初始化 (沿用 Day 4 项目)

我们将沿用 Day 4 创建的 vue3-counter-app 项目。 如果您还没有创建项目,请参考 Day 1 博客中的步骤进行初始化。 无需创建新的项目,我们将在已有的项目基础上进行开发。

步骤 2: 创建看板列表组件 (components/KanbanList.vue)

首先,我们需要创建一个 KanbanList.vue 组件,用于展示单个看板列表,并包含任务卡片列表。 在 src/components 目录下创建 KanbanList.vue 文件。

src/components/KanbanList.vue 文件内容如下:

<template>
  <div class="kanban-list" @dragover.prevent @drop="handleDrop">
    <h3>{
  { title }}</h3>
    <ul class="task-list">
      <li
        v-for="task in tasks"
        :key="task.id"
        class="task-card"
        draggable="true"
        @dragstart="handleDragStart(task)"
      >
        {
  { task.title }}
      </li>
    </ul>
  </div>
</template>

<script setup>
import { defineProps, defineEmits, ref } from 'vue';

const props = defineProps({
  title: {
    type: String,
    required: true
  },
  tasks: {
    type: Array,
    required: true
  }
});

const emit = defineEmits(['task-dropped']);

const draggingTask = ref(null); // 用于存储正在拖拽的任务卡片数据

const handleDragStart = (task) => {
  draggingTask.value = task; // 记录正在拖拽的任务卡片数据
  console.log('开始拖拽任务:', task.title);
};

const handleDrop = () => {
  if (draggingTask.value) {
    emit('task-dropped', draggingTask.value, props.title); // 触发 task-dropped 事件,并传递任务数据和目标列表标题
    draggingTask.value = null; // 清空正在拖拽的任务卡片数据
  }
};
</script>

<style scoped>
/* 组件样式省略,可以根据需要自行添加样式 */
.kanban-list {
  background-color: #f0f0f0;
  border-radius: 5px;
  paddin
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Neo Evolution

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值