Vue 可组合项非常强大,但如果您不小心,它们很快就会变得混乱且难以维护。
这就是为什么我确定了 13 个技巧,可以帮助您编写更好、更易于维护的可组合项。
无论您是构建简单的状态管理解决方案还是复杂的共享逻辑,这些技巧都将为您提供帮助:
您将学到的技巧是:
让我们深入研究每种模式,看看它们如何改进您的 Vue 应用程序。
别忘了,在下面评论你最喜欢的提示!
数据存储模式可以帮助避免通过多个组件层传递道具和事件。
一种情况是父母和孩子通过无休止的道具钻探和事件冒泡进行交流:
<!-- Parent.vue --> <template> <!-- But many more layers of components --> <Child :user="user" @change="onUserChange" /> </template> <script setup> const user = ref({ name: 'Alice' }) function onUserChange(updatedUser) { user.value = updatedUser } </script>
这会造成很大的复杂性,因为这些道具和事件必须在组件层次结构中来回移动。
更简单的解决方案是创建一个任何组件都可以导入的共享数据存储:
import { reactive, toRefs } from 'vue' const state = reactive({ user: { name: 'Alice' } }) export function useUserStore() { return toRefs(state) }
当兄弟或“表兄弟”组件需要在没有任何直接连接的情况下共享相同的数据时,数据存储模式也会有所帮助。
假设两个兄弟姐妹都需要相同的用户对象,但没有优雅的道具或事件路径。
这通常会导致在父状态或重复状态之间进行尴尬的数据处理。
更好的方法是依赖一个兄弟姐妹都可以使用的可组合存储:
// SiblingA.vue import { useUserStore } from './useUserStore' const { user } = useUserStore() // SiblingB.vue import { useUserStore } from './useUserStore' const { user } = useUserStore()
数据存储模式鼓励提供清晰的方法来更新共享状态。
一些开发人员将整个反应式对象暴露给世界,如下所示:
<!-- Parent.vue --> <template> <!-- But many more layers of components --> <Child :user="user" @change="onUserChange" /> </template> <script setup> const user = ref({ name: 'Alice' }) function onUserChange(updatedUser) { user.value = updatedUser } </script>
这使得任何人都可以直接从任何文件更改用户的 darkMode 属性,这可能会导致分散的、不受控制的突变。
更好的想法是将状态返回为只读以及定义更新如何发生的函数:
import { reactive, toRefs } from 'vue' const state = reactive({ user: { name: 'Alice' } }) export function useUserStore() { return toRefs(state) }
内联可组合模式通过将相关状态和逻辑收集到更小的函数中来帮助分解大型组件。
一个巨大的组件可能会将其所有引用和方法放在一个地方:
// SiblingA.vue import { useUserStore } from './useUserStore' const { user } = useUserStore() // SiblingB.vue import { useUserStore } from './useUserStore' const { user } = useUserStore()
这种设置很快就会变得难以管理。
相反,内联可组合项可以对逻辑进行分组并在本地提供。然后我们可以稍后将其提取到一个单独的文件中:
export const user = reactive({ darkMode: false })
精简可组合模式告诉我们将原始业务逻辑与 Vue 反应性分开,以便测试和维护变得更简单。
您可以将所有逻辑嵌入可组合项中:
import { reactive, readonly } from 'vue' const state = reactive({ darkMode: false }) export function toggleDarkMode() { state.darkMode = !state.darkMode } export function useUserStore() { return { darkMode: readonly(state.darkMode), toggleDarkMode } }
这迫使您在 Vue 环境中测试逻辑。
相反,将复杂的规则保留在纯函数中,并让可组合项仅处理反应式包装器:
<script setup> const count = ref(0) const user = ref({ name: 'Alice' }) // 500 more lines of intertwined code with watchers, methods, etc. </script>
异步同步可组合模式将同步和异步行为合并到一个可组合中,而不是创建单独的函数。
这就像 Nuxt 的 useAsyncData 的工作原理一样。
这里我们有一个可组合项,它可以返回承诺,同时还为同步使用提供即时反应属性:
<script setup> function useCounter() { const count = ref(0) const increment = () => count.value++ return { count, increment } } const { count, increment } = useCounter() </script>
选项对象模式可以通过期望单个配置对象来清除长参数列表。
这样的调用比较麻烦而且容易出错,添加新选项需要更新函数签名:
export function useCounter() { const count = ref(0) function increment() { count.value = (count.value * 3) / 2 } return { count, increment } }
每个参数代表什么并不明显。
接受选项对象的可组合项使所有内容保持描述性:
// counterLogic.js export function incrementCount(num) { return (num * 3) / 2 } // useCounter.js import { ref } from 'vue' import { incrementCount } from './counterLogic' export function useCounter() { const count = ref(0) function increment() { count.value = incrementCount(count.value) } return { count, increment } }
选项对象模式还建议每个属性的默认值。
假设某些字段存在的函数如果未传递,可能会出现问题:
import { ref } from 'vue' export function useAsyncOrSync() { const data = ref(null) const promise = fetch('/api') .then(res => res.json()) .then(json => { data.value = json return { data } }) return Object.assign(promise, { data }) }
最好使用安全默认值解构选项:
useRefHistory(someRef, true, 10, 500, 'click', false)
动态返回模式确保可组合项可以返回简单用例的单个值或具有更高级控件的扩展对象。
一些方法总是返回一个包含所有内容的对象:
<!-- Parent.vue --> <template> <!-- But many more layers of components --> <Child :user="user" @change="onUserChange" /> </template> <script setup> const user = ref({ name: 'Alice' }) function onUserChange(updatedUser) { user.value = updatedUser } </script>
任何只需要主要无功值的人都被迫处理额外的东西。
有条件返回单个引用或对象的可组合项解决了:
import { reactive, toRefs } from 'vue' const state = reactive({ user: { name: 'Alice' } }) export function useUserStore() { return toRefs(state) }
隐藏可组合项模式有助于避免在同一可组合项中混合互斥逻辑。
一些代码将多种模式或代码路径组合在一起:
// SiblingA.vue import { useUserStore } from './useUserStore' const { user } = useUserStore() // SiblingB.vue import { useUserStore } from './useUserStore' const { user } = useUserStore()
将每个路径拆分为自己的可组合项更加清晰,并且不会影响功能:
export const user = reactive({ darkMode: false })
灵活参数模式确保可组合项中的输入和输出被统一处理为反应数据或原始值,避免混淆。
一些代码检查输入是否是引用:
import { reactive, readonly } from 'vue' const state = reactive({ darkMode: false }) export function toggleDarkMode() { state.darkMode = !state.darkMode } export function useUserStore() { return { darkMode: readonly(state.darkMode), toggleDarkMode } }
相反,您可以立即转换。
通过使用 ref,如果输入是 ref,则将返回该 ref。否则,它将被转换为 ref:
<script setup> const count = ref(0) const user = ref({ name: 'Alice' }) // 500 more lines of intertwined code with watchers, methods, etc. </script>
当需要展开时,灵活参数模式也会使用 toValue。
没有它,代码可能会继续执行 isRef 检查:
<script setup> function useCounter() { const count = ref(0) const increment = () => count.value++ return { count, increment } } const { count, increment } = useCounter() </script>
调用更简单:
export function useCounter() { const count = ref(0) function increment() { count.value = (count.value * 3) / 2 } return { count, increment } }
Options to Composition 模式可让您以易于遵循的增量方式逐步将大型 Options API 组件迁移到 Composition API。
经典的选项组件可能会这样做:
// counterLogic.js export function incrementCount(num) { return (num * 3) / 2 } // useCounter.js import { ref } from 'vue' import { incrementCount } from './counterLogic' export function useCounter() { const count = ref(0) function increment() { count.value = incrementCount(count.value) } return { count, increment } }
数据、计算属性和方法是分散的。
将其转换为脚本设置将它们组合在一起,使其更易于遵循,并允许您使用这些模式:
import { ref } from 'vue' export function useAsyncOrSync() { const data = ref(null) const promise = fetch('/api') .then(res => res.json()) .then(json => { data.value = json return { data } }) return Object.assign(promise, { data }) }
这 13 个技巧将帮助您编写更好的 Vue 可组合项,更容易在应用程序中维护、测试和重用。
但我们只是触及了表面。
多年来,我收集了更多模式和技巧,并将它们全部放入可组合模式的深入课程中。
总共涵盖16种图案,每种图案有:
到这里了解更多。
哦,这门课程优惠至 1 月 15 日,所以您现在就可以享受超值折扣!
查看可组合设计模式
以上是您需要了解的 Vue 可组合技巧的详细内容。更多信息请关注PHP中文网其他相关文章!