翻译:Vue3 组合式API 完全指南

原文地址Mastering Vue 3 Composables: A Comprehensive Style Guide

原文作者是一名来自德国的全栈开发者,有媒体信息学的背景。


Vue 3 的发布迎来了一次变革,从 Options API 转向 Composition API。这一转变的核心在于“可组合性”的概念——利用 Vue 响应式功能的模块化功能。这一变化为框架注入了更大的灵活性和代码可重用性。然而,它也带来了挑战,特别是跨项目的可组合性实现不一致,这通常会导致复杂且难以维护的代码库。

本风格指南旨在协调可组合项的编码实践,重点是生成干净、可维护和可测试的代码。尽管可组合项可能看起来是一种新事物,但它们本质上只是函数。因此,本指南的建议基于经过时间考验的良好软件设计原则。

无论您是刚刚接触 Vue 3 还是一位致力于标准化团队编码风格的经验丰富的开发人员,本指南都可以作为综合资源。

文件命名

使用use前缀并遵循帕斯卡命名法

Goodts
useCounter.ts
useApiRequest.ts
Badts
counter.ts
APIrequest.ts

Composable 命名

使用描述性名称

Goodts
export function useUserData() {}
Badts
export function useData() {}

文件夹结构

将可组合项组织到composables文件夹中

Good
src/
|-- composables/
  |-- useCounter.ts
  |-- useUser.ts
  |-- useApiRequest.ts

参数传递

对四个或更多参数使用对象参数

Goodts
useUserData({ id: 1, fetchOnMount: true, token: 'abc', locale: 'en' })
Also Good: 参数比较少时ts
useUserData(1, true, 'session')
Badts
useUserData(1, true, 'session', 'en')

错误处理

暴露错误状态

Goodts
function useExampleGoodError() {
    const error = ref(null)
    try {
        // Do something
    }
    catch (e) {
        error.value = e
    }
    return { error }
}
Badts
function useExampleBadError() {
    try {
        // Do something
    }
    catch (e) {
        console.error('An error occurred', e)
    }
}

避免混合UI和业务逻辑

在可组合项中将 UI 与业务逻辑解耦

可组合项应专注于管理状态和业务逻辑,避免特定于 UI 的行为,例如 toast 或警报。将 UI 逻辑与业务逻辑分开将确保您的可组合项可重用和可测试。

Goodts
export function useUserData(userId) {
    const user = ref(null)
    const error = ref(null)
    const fetchUser = async () => {
        try {
            const response = await axios.get(`/users/${userId}`)
            user.value = response.data
        }
        catch (e) {
            error.value = e
        }
    }

    return { user, error, fetchUser }
}
在组件里使用html
<script lang="ts" setup>
  const {user,error,fetchUser} = useUserData(1)
  watch(error, newValue => {
    if (newValue) {
      showToast('An error occurred')
    }
  })
</script>
Badts
export function useUserData(userId) {
    const user = ref(null)
    const fetchUser = async () => {
        try {
            const response = await axios.get(`/users/${userId}`)
            user.value = response.data
        }
        catch (e) {
            showToast('An error occurred')
        }
    }

    return { user, fetchUser }
}

可组合项的剖析

良好地构建可组合项

遵循明确定义的结构的可组合项更容易理解、使用和维护。理想情况下,它应该由以下组件组成:

  • 主要状态: 可组合项管理的主要只读状态。
  • 支持状态:附加只读状态,保存API请求或错误状态等的值。
  • 方法:负责更新主要和支持状态的功能。他们可以调用API、管理cookie,甚至调用其他可组合项。

通过确保您的可组合项遵循这种解剖结构,您可以使开发者更轻松地使用它们,从而提高整个项目的代码质量。

功能核心,命令式外壳

(可选) 使用功能核心命令式外壳模式

构建可组合项,使核心逻辑具有功能性且没有副作用,而命令式外壳则处理Vue特定个的或副作用操作。遵循这一原则可以使您的可组合项更易于测试、调试和维护。

Goodts
// 功能核心
const calculate = (a, b) => a + b

// 命令式外壳
export function useCalculator() {
    const result = ref(0)

    const add = (a, b) => {
        result.value = calculate(a, b)
    }

    return { result, add }
}
Badts
// 混合了主要功能和副作用函数
export function useCalculator() {
    const result = ref(0)

    const add = (a, b) => {
        // 核心逻辑中的副作用
        console.log('Adding ' + a + ' and ' + b)

        result.value = a + b
    }

    return { result, add }
}

单一职责原则

对可组合项使用SRP

可组合项应遵循单一职责原则,这意味着它应该只有一个更改理由。换句话说,可组合项应该只有一项工作或职责。违反此原则可能会导致可组合项难以理解、维护和测试。

Goodts
export function useCounter() {
    const count = ref(0)

    const increment = () => {
        count.value++
    }

    const decrement = () => {
        count.value--
    }

    return { count, increment, decrement }
}

可组合项的文件结构

可组合项功能的一致排序

虽然可以调整精确的顺序以满足您的项目或团队的需求,但至关重要的是,所选顺序在整个代码库中保持一致。

以下是文件结构的建议:

  1. 初始化:用于设置初始化逻辑的代码
  2. Refs:响应式数据
  3. Computed:计算属性
  4. Methods:方法
  5. Lifecycle:生命周期钩子
  6. Watchers:观察者

这只是一个示例的顺序,您可以根据自己的需求进行调整。但要确保在整个代码库中保持一致。

结论

本文提出的指南旨在提供编写干净、可测试且高效的Vue3可组合项的最佳实践。虽然这些建议源于既定的软件设计原则和实践经验的组合,但它们绝不是详尽的或普遍适用的。

编程往往更像一门艺术而不是一门科学。随着您在Vue之旅中不断成长,您可能发现更适合您的特定用例的不同策略和模式。关键是要保持一致、可扩展且可维护的代码库。因此,请随意根据您的项目的需要调整这些指南。

我愿意接受更多的想法、改进和现实世界中的例子。如果您有任何适合您的建议或不同方法,请随时在下面的评论中分享。我们可以共同发展这些指南,使其成为对Vue社区更有用的资源。

本站为什么要从 Hexo 迁移到 Nuxt

翻译 - 如何在 Vue 中使用Props变体

评论区

评论加载中...