【JS】深度揭秘!Vue3 Composition API全面教程与实战案例,助你轻松掌握前端新利器

随着前端技术的不断发展,组件化编程已经成为主流。在 Vue2 中,Options API 的方式虽然直观,但在大型应用中容易导致代码冗余和逻辑分散。而 Vue3 引入的 Composition API 则提供了一种更灵活、高效的组件逻辑组织方式,使得代码更易于维护和复用。那么,Composition API 究竟有哪些优势?如何在实际项目中应用呢?让我们一起深入探讨!

更多实用工具

【OpenAI】获取OpenAI API Key的多种方式全攻略:从入门到精通,再到详解教程!!

【VScode】VSCode中的智能AI-GPT编程利器,全面揭秘ChatMoss & ChatGPT中文版

【GPT-o1系列模型!支持Open API调用、自定义助手、文件上传等强大功能,助您提升工作效率!】>>>点击跳转 - CodeMoss & ChatGPT-AI中文版

在这里插入图片描述

什么是 Composition API

Composition API 是 Vue3 引入的一组新的 API,用于组织和复用组件逻辑。与传统的 Options API(如 data、methods、computed 等)不同,Composition API 通过函数式的方式将相关的逻辑组合在一起,使代码更具可读性和可维护性。

主要特点包括:

  • 逻辑复用更便捷:通过组合函数(Composable Functions),可以轻松复用和共享逻辑。
  • 代码组织更清晰:将相关的状态和行为放在同一个函数中,减少了逻辑分散的问题。
  • TypeScript 更友好:更好地支持类型推导,提升开发体验。

在这里插入图片描述

Composition API 与 Options API 的对比

在 Vue2 中,Options API 是主要的组件定义方式,使用 data、methods、computed 等选项来组织组件逻辑。然而,随着组件规模增大,Options API 的代码容易变得臃肿,逻辑分散难以维护。

特性Options APIComposition API
逻辑复用通过 mixins 或高阶组件实现,较为复杂通过组合函数实现,简洁直观
代码组织按选项组织(data、methods 等)按功能组织,逻辑更聚焦
TypeScript 支持限制较多,类型推导困难更加友好,类型推导更精准
可读性简单组件易读,复杂组件易乱无论组件大小,都保持良好可读性

Composition API 的核心概念

要全面掌握 Composition API,首先需要理解其核心概念和基本用法。下面,我们将逐一解析这些关键点。

Setup 函数

setup 函数是 Composition API 的入口,用于替代 Options API 中的 data、methods 等选项。setup 在组件创建之前执行,是一个用于定义组件逻辑的地方。

示例:

<template>
  <div>
    <p>{{ count }}</p>
    <button @click="increment">增加</button>
  </div>
</template>

<script>
import { ref } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const increment = () => {
      count.value++
    }
    return {
      count,
      increment
    }
  }
}
</script>

响应式数据:ref 和 reactive

响应式是 Vue 的核心特性之一。Composition API 提供了 refreactive 两种方式来定义响应式数据。

  • ref:用于创建基本类型的响应式数据。
  • reactive:用于创建对象或数组的响应式数据。

示例:

import { ref, reactive } from 'vue'

// 使用 ref 创建响应式基本类型
const count = ref(0)

// 使用 reactive 创建响应式对象
const user = reactive({
  name: '张三',
  age: 25
})

计算属性和侦听器:computed 和 watch

computed 用于创建计算属性,基于其他响应式数据自动计算其值,并在依赖变化时自动更新。watch 则用于侦听响应式数据的变化,并在变化时执行回调函数。

在这里插入图片描述

示例:

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

const count = ref(0)

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

// 侦听器
watch(count, (newVal, oldVal) => {
  console.log(`count 从 ${oldVal} 变为 ${newVal}`)
})

生命周期钩子

Composition API 提供了一系列生命周期钩子,如 onMountedonUnmounted 等,用于在组件的不同生命周期阶段执行相应的逻辑。

示例:

import { onMounted, onUnmounted } from 'vue'

export default {
  setup() {
    onMounted(() => {
      console.log('组件已挂载')
    })
    
    onUnmounted(() => {
      console.log('组件已卸载')
    })
  }
}

实战案例:使用 Composition API 开发 Todo 应用

通过一个实际的应用案例,我们将全面展示如何使用 Composition API 开发一个简单的 Todo 应用。这不仅能够帮助你理解 Composition API 的基本用法,还能让你看到其在实际项目中的强大之处。

项目结构

为了保持项目的清晰和可维护性,我们将采用以下的项目结构:

src/
|-- components/
|   |-- TodoList.vue
|   |-- TodoItem.vue
|-- composables/
|   |-- useTodos.js
|-- App.vue
|-- main.js

实现步骤

创建响应式数据

首先,我们需要定义 Todo 项目的数据结构,并创建响应式的数据源。在 composables 目录下创建 useTodos.js,用于管理 Todo 相关的逻辑。

// src/composables/useTodos.js
import { ref, computed } from 'vue'

export function useTodos() {
  const todos = ref([
    { id: 1, text: '学习 Vue3', completed: false },
    { id: 2, text: '编写 Composition API 教程', completed: false }
  ])

  const newTodo = ref('')

  const addTodo = () => {
    if (newTodo.value.trim()) {
      todos.value.push({
        id: Date.now(),
        text: newTodo.value,
        completed: false
      })
      newTodo.value = ''
    }
  }

  const removeTodo = (id) => {
    todos.value = todos.value.filter(todo => todo.id !== id)
  }

  const completedCount = computed(() => {
    return todos.value.filter(todo => todo.completed).length
  })

  const totalCount = computed(() => todos.value.length)

  return {
    todos,
    newTodo,
    addTodo,
    removeTodo,
    completedCount,
    totalCount
  }
}
添加和删除 Todo

TodoList.vue 中,我们将使用 useTodos 组合函数,来管理 Todo 项目的添加和删除逻辑。

<!-- src/components/TodoList.vue -->
<template>
  <div>
    <h2>我的 Todo 列表</h2>
    <input v-model="newTodo" @keyup.enter="addTodo" placeholder="添加新的 Todo" />
    <button @click="addTodo">添加</button>
    <ul>
      <TodoItem v-for="todo in todos" :key="todo.id" :todo="todo" @remove="removeTodo" />
    </ul>
    <p>已完成:{{ completedCount }}/总数:{{ totalCount }}</p>
  </div>
</template>

<script>
import { useTodos } from '../composables/useTodos'
import TodoItem from './TodoItem.vue'

export default {
  components: { TodoItem },
  setup() {
    const { todos, newTodo, addTodo, removeTodo, completedCount, totalCount } = useTodos()
    return { todos, newTodo, addTodo, removeTodo, completedCount, totalCount }
  }
}
</script>
过滤和计算功能

useTodos.js 中,我们已经实现了 completedCounttotalCount 这两个计算属性,用于统计已完成的 Todo 数量和总数量。在 TodoList.vue 中,我们展示了这些统计数据。

代码详解

通过上述步骤,我们已经初步构建了一个功能完整的 Todo 应用。下面,我们将深入解析其中的关键代码,了解 Composition API 如何让代码更简洁、高效。

组合函数:useTodos.js

组合函数 useTodos 封装了所有与 Todo 相关的逻辑,包括数据的管理、添加和删除功能、以及统计计算。这种封装方式使得逻辑高度聚合,易于维护和复用。

import { ref, computed } from 'vue'

export function useTodos() {
  const todos = ref([
    { id: 1, text: '学习 Vue3', completed: false },
    { id: 2, text: '编写 Composition API 教程', completed: false }
  ])

  const newTodo = ref('')

  const addTodo = () => {
    if (newTodo.value.trim()) {
      todos.value.push({
        id: Date.now(),
        text: newTodo.value,
        completed: false
      })
      newTodo.value = ''
    }
  }

  const removeTodo = (id) => {
    todos.value = todos.value.filter(todo => todo.id !== id)
  }

  const completedCount = computed(() => {
    return todos.value.filter(todo => todo.completed).length
  })

  const totalCount = computed(() => todos.value.length)

  return {
    todos,
    newTodo,
    addTodo,
    removeTodo,
    completedCount,
    totalCount
  }
}

关键点解析:

  • 响应式数据定义:使用 ref 创建 todosnewTodo,确保它们的变化能够触发视图更新。
  • 添加 TodoaddTodo 方法检查输入内容是否为空,避免添加空的 Todo 项目。
  • 删除 TodoremoveTodo 方法通过过滤掉指定 ID 的 Todo 项目实现删除功能。
  • 计算属性completedCounttotalCount 使用 computed 来自动计算已完成的数量和总数量,避免手动管理状态。
组件中的组合函数应用

TodoList.vue 中,通过调用 useTodos,我们将所有的逻辑和数据引入组件,使得组件本身保持简洁,只负责展示和用户交互。

import { useTodos } from '../composables/useTodos'

export default {
  setup() {
    const { todos, newTodo, addTodo, removeTodo, completedCount, totalCount } = useTodos()
    return { todos, newTodo, addTodo, removeTodo, completedCount, totalCount }
  }
}

这种方式不仅提高了代码的复用性,还使得组件逻辑更加清晰,便于测试和维护。

Composition API 的高级用法

掌握了基本的 Composition API 用法后,我们可以进一步探索其高级特性,提升开发效率。

自定义组合函数(Composable)

组合函数是 Composition API 的核心概念,通过将相关的逻辑封装在一个函数中,实现逻辑的复用和模块化。

示例:

假设我们有多个组件需要使用表单验证逻辑,我们可以创建一个组合函数 useFormValidation 来复用这部分逻辑。

// src/composables/useFormValidation.js
import { ref, computed } from 'vue'

export function useFormValidation() {
  const form = ref({
    username: '',
    email: ''
  })

  const errors = ref({})

  const validate = () => {
    errors.value = {}
    if (!form.value.username) {
      errors.value.username = '用户名不能为空'
    }
    if (!form.value.email) {
      errors.value.email = '邮箱不能为空'
    } else if (!/\S+@\S+\.\S+/.test(form.value.email)) {
      errors.value.email = '邮箱格式不正确'
    }
    return Object.keys(errors.value).length === 0
  }

  return {
    form,
    errors,
    validate
  }
}

在组件中使用:

<script>
import { useFormValidation } from '../composables/useFormValidation'

export default {
  setup() {
    const { form, errors, validate } = useFormValidation()

    const submit = () => {
      if (validate()) {
        // 提交逻辑
      }
    }

    return { form, errors, submit }
  }
}
</script>

依赖注入:provide 和 inject

provideinject 允许组件在层级结构中共享依赖,而无需通过 props 或事件传递。这在大型应用中非常有用,特别是在需要跨多个层级传递数据时。

示例:

// 父组件
import { provide, ref } from 'vue'

export default {
  setup() {
    const appName = ref('我的应用')
    provide('appName', appName)
  }
}

// 子组件
import { inject } from 'vue'

export default {
  setup() {
    const appName = inject('appName')
    return { appName }
  }
}

最佳实践与性能优化

应用 Composition API 时,遵循一些最佳实践不仅能提升代码质量,还能优化应用性能。

组织和复用代码

  • 组合函数模块化:将相关逻辑封装在独立的组合函数中,提升代码的可复用性和可维护性。
  • 避免过度抽象:虽然组合函数可以复用逻辑,但过度抽象可能导致代码难以理解,应在复用性和可读性之间找到平衡。

避免不必要的响应式

响应式数据会引入一定的性能开销,特别是在处理大量数据时。因此,合理选择响应式数据的范围和深度非常重要。

  • 使用 shallowRefshallowReactive:在不需要深度响应时,使用浅响应式引用。
  • 惰性计算:仅在需要时进行计算,避免不必要的计算属性。

示例:

import { shallowRef } from 'vue'

const user = shallowRef({
  name: '张三',
  age: 25
})

更多实用工具

【OpenAI】获取OpenAI API Key的多种方式全攻略:从入门到精通,再到详解教程!!

【VScode】VSCode中的智能AI-GPT编程利器,全面揭秘ChatMoss & ChatGPT中文版

【GPT-o1系列模型!支持Open API调用、自定义助手、文件上传等强大功能,助您提升工作效率!】>>>点击跳转 - CodeMoss & ChatGPT-AI中文版

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

XinZong-千鑫

在线乞讨,行行好吧!

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

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

打赏作者

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

抵扣说明:

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

余额充值