Vue3,用组合的方式来编写更好的代码(1/5)
ztj100 2024-11-26 11:15 13 浏览 0 评论
到目前为止,可组合是组织Vue 3应用中业务逻辑的最佳方式。
它们让你把小块的逻辑提取到函数中,我们可以轻松地重复使用,这样的代码更容易编写和阅读。
由于这种编写Vue代码的方式相对较新,你可能想知道在编写可组合代码的最佳做法是什么。本系列教程将作为一个指南,告诉你如何编写值得信赖且可靠组合式代码。
以下是我们将讨论的内容。
- 如何使用选项对象参数来使组合更有配置性
- 使用 ref 和 unref 来使我们的论证更加灵活
- 让返回值更有用的一个简单方法
- 为什么从接口开始会使我们组合会更强大
- 如何使用不需要 await 的异步代码--让你的代码更容易理解
首先, 我们先不看什么是可组合式?
什么是可组合式?
根据Vue文档,可组合是 "利用Vue Composition API来封装和重用有状态逻辑的函数"。
这意味着任何使用响应式的代码都可以变成一个可组合的。
下面是一个来自Vue.js文档的useMouse可组合的简单例子。
import { ref, onMounted, onUnmounted } from 'vue'
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 }
}
我们将状态定义为 refs,然后在鼠标移动时更新该状态。通过返回x和y refs,我们可以在任何组件(甚至是另一个可组合的组件)中使用它们。
下面是我们如何在一个组件中使用这个可组合的。
<template>
X: {{ x }} Y: {{ y }}
</template>
<script setup>
import { useMouse } from './useMouse';
const { x, y } = useMouse();
</script>
正如你所看到的,使用 useMouse 组合就可以重复使用所有这些逻辑。只需很少的额外代码,我们就能在我们的组件中抓取鼠标坐标。
选项对象参数
大多数可组合程序有一个或两个必要的输入。然后有一系列的可选参数来帮助配置可组合的工作方式。
当配置你的可组合的时候,你可以传入一个选项对象,而不是传入一长串的参数,。
// 使用一个选项对象
const title = useTitle('A new title', { titleTemplate: '>> %s <<' });
// Title is now ">> A new title <<"
// 使用入一长串的参数
const title = useTitle('A new title', '>> %s <<');
// Title is now ">> A new title <<"
将选项作为一个整体对象而不是参数传入,给我们带来一些好处。
首先,我们不需要记住参数的正确顺序。现在有了TypeScript和编辑器自动完成功能,这已经不是一个问题了,但它仍然有区别。对于一个Javascript对象,键的顺序并不重要。
第二,代码更易读,因为我们知道这个选项是做什么的。代码即注释。我们不需要在源代码中寻找,也不需要依靠我们的IDE来让我们知道。
第三,以后再添加新的选项就容易多了。这既适用于向可组合本身添加新选项,也适用于在使用可组合时添加选项。
所以,使用一个选项对象会更好。但我们如何实现呢?
以可组合的方式实施
下面是如何在一个可组合的中实现选项对象模式。
export function useMouse(options) {
const {
asArray = false,
throttle = false,
} = options;
// ...
};
在这里,如果参数是必需的,我们可以接受一两个参数,然后最后一个参数是选项对象。所以在这个例子中,useMouse没有必要的参数,只有选项对象。
下一步是分解选项对象。通过解构,我们可以访问所有的值,并明确地为每个可能的选项提供默认值。
现在,我们将看看VueUse中的两个不同的组合是如何应用该模式的。VueUse是Vue 3的一个开源组合集合,编写得非常好。它是学习如何编写可组合代码的一个很好的资源
https://vueuse.org/
首先,我们看看useTitle,然后再看看useRefHistory是如何工作的。
useTitle
useTitle是一个相当简单的组合。它用来更新页面的标题。
const title = useTitle('Initial Page Title');
// Title: "Initial Page Title"
title.value = 'New Page Title';
// Title: "New Page Title"
它也有几个选项以获得额外的灵活性。
可以提供一个 titleTemplate,还可以设置它来观察(observe)其他脚本可能做出的任何改变的标题(使用MutationObserver)。
const titleOptions = {
titleTemplate: '>> %s <<',
observe: true,
};
下面是使用选项对象的方式:
const title = useTitle('Initial Page Title', {
titleTemplate: '>> %s <<',
observe: true,
});
// Title: ">> Initial Page Title <<"
title.value = 'New Page Title';
// Title: ">> New Page Title <<"
当你查看useTitle的源码时,它是这么做的:
export function useTitle(newTitle, options) {
const {
document = defaultDocument,
observe = false,
titleTemplate = '%s',
} = options;
// ...
}
useTitle可组合式有一个必要的参数,然后是一个 options 对象。在这之后,它完全按照这里描述的模式实现其余部分。
现在让我们看看一个稍微复杂的可组合,它也使用这个选项对象模式。
useRefHistory
useRefHistory 更有趣一些。它可以让你跟踪对一个 ref 所做的所有改变,可以容易地执行撤销和重做操作。
// Set up the count ref and track it
const count = ref(0);
const { undo } = useRefHistory(count);
// Increment the count
count.value++;
// Log out the count, undo, and log again
console.log(counter.value); // 1
undo();
console.log(counter.value); // 0
此可组合可采用许多不同的选项
{
deep: false,
flush: 'pre',
capacity: -1,
clone: false,
// ...
}
我们可以把选项对象作为第二个参数传入,以进一步配置这个可组合的行为方式,与我们之前的例子一样。
const state = ref({});
const { undo, redo } = useRefHistory(state, {
deep: true, // 追踪对象和数组内部的变化
capacity: 15, // 限制我们追踪的步骤数量
});
如果我们看一下这个源代码,我们会发现它使用了与useTitle完全相同的对象重构模式。
export function useRefHistory(source, options) {
const {
deep = false,
flush = 'pre',
eventFilter,
} = options;
// ...
}
然而,在这个例子中,我们只在开始时从选项对象中抽出几个值。
这是因为useRefHistory在内部依赖于useManualRefHistory可组合程序。其余的选项将作为该可组合的选项对象在后面的可组合中传递。
// ...
const manualHistory = useManualRefHistory(
source,
{
// Pass along the options object to another composable
...options,
clone: options.clone || deep,
setSource,
},
);
// ...
把所有的东西集中起来
本文是我们“编写更好的组合”系列的第一部分。
我们研究了如何将一个选项对象作为参数添加到组件中,从而使组件的可配置性大大增强。例如,你不需要担心参数的排序,也不需要记住每个参数的作用,而且向一个对象添加更多的选项要比更新传入的参数容易得多。
但我们并不只是看了这个模式本身。我们还看到了VueUse的组合物 useTitle 和useRefHistory 是如何实现这一模式的。他们的方式略有不同,但由于这是一个简单的模式,你可以做的变化不多。
本系列的下一篇文章将探讨我们如何接受Refs和常规Javascript值作为参数。
// 传递一个 ref 值,可以工作
const countRef = ref(2);
useCount(countRef);
// 或者只给一个简单的数字
const countRef = useRef(2);
这增加了灵活性,允许我们在应用程序的更多情况下使用组合。
作者:Michael Thiessen 译者:小智 来源:vuemastery 原文: https://www.vuemastery.com/blog/coding-btter-composables-1-of-5
相关推荐
- 如何将数据仓库迁移到阿里云 AnalyticDB for PostgreSQL
-
阿里云AnalyticDBforPostgreSQL(以下简称ADBPG,即原HybridDBforPostgreSQL)为基于PostgreSQL内核的MPP架构的实时数据仓库服务,可以...
- Python数据分析:探索性分析
-
写在前面如果你忘记了前面的文章,可以看看加深印象:Python数据处理...
- C++基础语法梳理:算法丨十大排序算法(二)
-
本期是C++基础语法分享的第十六节,今天给大家来梳理一下十大排序算法后五个!归并排序...
- C 语言的标准库有哪些
-
C语言的标准库并不是一个单一的实体,而是由一系列头文件(headerfiles)组成的集合。每个头文件声明了一组相关的函数、宏、类型和常量。程序员通过在代码中使用#include<...
- [深度学习] ncnn安装和调用基础教程
-
1介绍ncnn是腾讯开发的一个为手机端极致优化的高性能神经网络前向计算框架,无第三方依赖,跨平台,但是通常都需要protobuf和opencv。ncnn目前已在腾讯多款应用中使用,如QQ,Qzon...
- 用rust实现经典的冒泡排序和快速排序
-
1.假设待排序数组如下letmutarr=[5,3,8,4,2,7,1];...
- ncnn+PPYOLOv2首次结合!全网最详细代码解读来了
-
编辑:好困LRS【新智元导读】今天给大家安利一个宝藏仓库miemiedetection,该仓库集合了PPYOLO、PPYOLOv2、PPYOLOE三个算法pytorch实现三合一,其中的PPYOL...
- C++特性使用建议
-
1.引用参数使用引用替代指针且所有不变的引用参数必须加上const。在C语言中,如果函数需要修改变量的值,参数必须为指针,如...
- Qt4/5升级到Qt6吐血经验总结V202308
-
00:直观总结增加了很多轮子,同时原有模块拆分的也更细致,估计为了方便拓展个管理。把一些过度封装的东西移除了(比如同样的功能有多个函数),保证了只有一个函数执行该功能。把一些Qt5中兼容Qt4的方法废...
- 到底什么是C++11新特性,请看下文
-
C++11是一个比较大的更新,引入了很多新特性,以下是对这些特性的详细解释,帮助您快速理解C++11的内容1.自动类型推导(auto和decltype)...
- 掌握C++11这些特性,代码简洁性、安全性和性能轻松跃升!
-
C++11(又称C++0x)是C++编程语言的一次重大更新,引入了许多新特性,显著提升了代码简洁性、安全性和性能。以下是主要特性的分类介绍及示例:一、核心语言特性1.自动类型推导(auto)编译器自...
- 经典算法——凸包算法
-
凸包算法(ConvexHull)一、概念与问题描述凸包是指在平面上给定一组点,找到包含这些点的最小面积或最小周长的凸多边形。这个多边形没有任何内凹部分,即从一个多边形内的任意一点画一条线到多边形边界...
- 一起学习c++11——c++11中的新增的容器
-
c++11新增的容器1:array当时的初衷是希望提供一个在栈上分配的,定长数组,而且可以使用stl中的模板算法。array的用法如下:#include<string>#includ...
- C++ 编程中的一些最佳实践
-
1.遵循代码简洁原则尽量避免冗余代码,通过模块化设计、清晰的命名和良好的结构,让代码更易于阅读和维护...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- node卸载 (33)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- exceptionininitializererror (33)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)