按照一个系统的来说,可组合项负责存储主要业务逻辑(如计算、操作、流程),因此它们是应用程序的关键部分。
通过重构构建新可组合项的方法,使它们可维护、易于测试且真正有用。
在本文中,我将总结我们创建的想法,并将它们与我在几篇文章中读到的良好实践和设计模式相结合。
所以本文将分为三个部分:
通用设计模式
我的建议
进一步阅读
享受并且让我知道您在项目中使用的模式和实践🚀
通用设计模式
我认为了解构建可组合项模式的最佳来源实际上是 Vue.js 文档,您可以在此处查看(https://vuejs.org/guide/reusability/composables.html)
基本可组合
Vue 文档显示了以下 useMouse 可组合项的示例:
Vue 文档显示了以下 useMouse 可组合项的示例: // mouse.js import { ref, onMounted, onUnmounted } from 'vue' // 按照惯例,可组合函数名称以“use”开头 export function useMouse() { // 由可组合项封装和管理的状态 const x = ref(0) const y = ref(0) // 可组合项可以随着时间的推移更新其托管状态。 function update(event) { x.value = event.pageX y.value = event.pageY } // 可组合项还可以挂接到其所有者组件的 // 设置和拆卸副作用的生命周期。 onMounted(() => window.addEventListener('mousemove', update)) onUnmounted(() => window.removeEventListener('mousemove', update)) // 将托管状态公开为返回值 return { x, y } }
稍后可以在组件中使用它,如下所示:
<script setup> import { useMouse } from './mouse.js' const { x, y } = useMouse() </script> <template>Mouse position is at: {{ x }}, {{ y }}</template>
异步可组合项
为了获取数据,Vue 建议使用以下可组合结构:
import { ref, watchEffect, toValue } from 'vue' export function useFetch(url) { const data = ref(null) const error = ref(null) watchEffect(() => { // 获取之前重置状态.. data.value = null error.value = null // toValue() 解开潜在的 refs 或 getters fetch(toValue(url)) .then((res) => res.json()) .then((json) => (data.value = json)) .catch((err) => (error.value = err)) }) return { data, error } }
然后可以在组件中使用它,如下所示:
<script setup> import { useFetch } from './fetch.js' const { data, error } = useFetch('...') </script>
可组合合约
根据上面的示例,以下是所有可组合项都应遵循的约定:
例如,可组合文件名应以 use 开头useSomeAmazingFeature.ts
它可以接受输入参数,这些参数可以是字符串等基本类型,也可以接受 refs 和 getter,但它需要使用 toValue 帮助器
可组合项应该返回一个 ref 值,可以在解构可组合项后访问该值,例如const { x, y } = useMouse()
可组合项可以保存可以在应用程序中访问和修改的全局状态。
可组合性可能会导致副作用,例如添加窗口事件侦听器,但在卸载组件时应清除它们。
<script setup>可组合项只能在钩子中调用setup()。它们也应该在这些上下文中同步调用。在某些情况下,您还可以在生命周期挂钩中调用它们,例如onMounted().
可组合项可以调用内部的其他可组合项。
可组合项应在内部包装某些逻辑,当过于复杂时,应将它们提取到单独的可组合项中以便于测试。
我的建议
我已经为我的工作项目和开源项目构建了多个可组合项 - NuxtAlgolia、NuxtCloudinary、NuxtMedusa,因此基于这些,我想根据我的经验在上面的合同中添加一些要点。
>有状态或/和纯函数可组合项
在代码标准化的某个时刻,您可能会得出这样的结论:您希望对可组合项中的状态保留做出决定。
最容易测试的函数是那些不存储任何状态的函数(即它们是简单的输入/输出函数),例如负责将字节转换为人类可读值的可组合函数。它接受一个值并返回一个不同的值 - 它不存储任何状态。
别误会我的意思,你不必做出决定OR。您可以完全保留有状态和无状态可组合项。但这应该是一个书面决定,以便以后更容易与他们合作 🙂
可组合项的单元测试
我们希望使用 Vitest 为我们的前端应用程序实施单元测试。在后端工作时,进行单元测试代码覆盖率非常有用,因为您主要关注逻辑。然而,在前端,您通常使用视觉效果。
因此,我们认为对整个组件进行单元测试可能不是最好的主意,因为我们基本上将对框架本身进行单元测试(如果按下按钮,检查状态是否更改或模式是否打开)。
由于我们已将所有业务逻辑移至可组合项(基本上是 TypeScript 函数)内,因此它们很容易使用 Vitest 进行测试,并且允许我们拥有更稳定的系统。
可组合项的范围
不久前,在 VueStorefront 中,我们开发了自己的可组合方法(早在它们实际上像这样被调用之前)。在我们的方法中,我们使用可组合项来映射电子商务的业务领域,如下所示:
const { cart, load, addItem, removeItem, remove, ... } = useCart()
这种方法绝对有用,因为它允许将域包装在一个函数中。在诸如useProduct或 之useCategory类的更简单的示例中,实现和维护相对简单。然而,正如您在此处的示例中所看到的,useCart当包装一个包含更多逻辑而不仅仅是数据获取的域时,这个可组合项正在发展成为一种非常难以开发和维护的形状。
此时,我开始为 Nuxt 生态系统做出贡献,其中引入了不同的方法。在这种新方法中,每个可组合项仅负责一件事。因此,useCart我们的想法不是构建一个巨大的可组合项,而是为每个功能构建可组合项useAddToCart,例如useFetchCart,,,useRemovefromCart等等。
因此,维护和测试这些可组合项应该更容易 🙂
进一步阅读
这将是我的研究的全部内容。如果您想了解有关此主题的更多信息,请务必查看以下文章:
https://vuejs.org/guide/reusability/composables.html
https://vueschool.io/articles/vuejs-tutorials/what-is-a-vue-js-composable/
https://blog.logrocket.com/getting-started-vue-composables/
https://macopedia.com/blog/news/how-can-vue-3-composables-make-your-life-easier文章来源:https://www.toymoban.com/diary/vue/339.html
文章来源地址https://www.toymoban.com/diary/vue/339.html
到此这篇关于Vue 可组合项的良好实践和设计模式的文章就介绍到这了,更多相关内容可以在右上角搜索或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!