Vue3: 二次封装Tdesign中的FileUpload组件-hook(更为易用!)

初衷

TDesign 是腾讯各业务团队在服务业务过程中沉淀的一套企业级设计体系。

当我们使用Tdesign中的FileUpload组件时,我们可能希望对其进行二次封装,以满足特定的需求或增加额外的功能。我们的初衷是让这个组件更加灵活、易用,并且能够适应不同的场景。

通过二次封装,我们可以将其整合到我们的应用程序中,使其更符合我们的设计规范和UI风格。 之前写有一篇关于:

Vue3: 二次封装WangEditor富文本编辑器-hook

也得到了不少的好评,确实在工作中,如果遇到有一些公用的组件,不妨结合它们的官方文档进行一下定制,定制成符合我们业务需求的组件。

后面,我将在图片上传和视频上传,做一下hooks封装, 在开始实战总结之前,先说一下什么是hooks,有什么好处

hooks介绍

Hooks封装是React中一种强大的编程模式 尽管Vue3中没有像React中的Hooks一样的编程模式,但Vue3引入了Composition API,提供了类似于Hooks的功能,具有一些类似的魅力:

  1. 逻辑复用:Composition API允许将逻辑封装到可复用的函数中,称为"composition function"。这样可以将一些常见的逻辑和功能进行封装,并在多个组件中进行复用,从而减少代码的重复。
  2. 更好的组件组合性:通过Composition API的组合函数,我们可以更灵活地组合组件逻辑,并将其粒度化。这使得组件更加可组合,不再受限于单一的渲染函数和生命周期钩子。
  3. 提高代码可读性:使用可重用的composition function,可以将组件的逻辑细分为更小的部分,使得代码更加清晰和易于阅读。同时,通过Composition API的函数式风格,我们可以更好地组织和维护代码。
  4. 更好的测试性:通过将逻辑封装到composition function中,可以更容易地进行单元测试。我们可以针对每个composition function编写独立的测试,并更好地模拟输入和验证输出,提高代码质量和可维护性。
  5. 更好的性能优化:Composition API提供了更多的工具,例如响应式、计算属性和watch等,用于处理和优化应用的状态和数据流。这使得性能优化更加清晰和高效。

虽然Vue3中的Composition API与React Hooks略有不同,但它们都带来了类似的魅力,包括逻辑复用、可读性的提高、更好的组件组合性、更好的测试性和更好的性能优化。通过合理使用Composition API,我们可以更好地开发Vue3应用,提高开发效率和代码质量。

那么接下来,我将通过图片上传和视频上传,封装hooks的全过程做一下总结。

二次封装FileUpload实现图片、视频上传

介绍Tdesign中FileUpload文档属性

在做封装之前,我们需要知道FileUpload提供了哪些属性方法,后面我们需要在此基础上做扩展. 这里只贴出较为关键和需要扩展的几个属性方法:

requestMethod

beforeUpload

该方法可以不用写入hooks中,可以在具体需求的地方,单独编写。因为文件大小、文件类型等相关需求需要按产品的设计而定,所以不适宜写在hooks

至于文件大小限制,upload组件早有提供,可以直接传入相应参数

sizeLimit

如下代码:

html 复制代码
<t-upload
    ref="imageRef"
    v-model="images"
    theme="custom"
    accept="image/jpg,image/jpeg,image/png,image/gif"
    multiple
    allow-upload-duplicate-file
    :max="10"
    :request-method="uploadImage"
    :before-upload="beforeUpload"
    :size-limit="{ size: 1, unit: 'MB', message: '上传的图片不符合要求,请重新上传' }"
    @validate="onUploadValidate"
>
    <t-icon name="add" class="icon" />
</t-upload>
html 复制代码
<t-upload
    ref="imageMultiRef"
    v-model="multiImages"
    theme="custom"
    accept="image/jpg,image/jpeg,image/png,image/gif"
    allow-upload-duplicate-file
    :request-method="uploadMultiImage"
    :before-upload="beforeUpload"
    :size-limit="{ size: 1, unit: 'MB', message: '上传的图片不符合要求,请重新上传' }"
    @validate="onUploadValidate"
>
    <t-icon name="add" size="30" class="icon" />
    <span>上传图片</span>
</t-upload>

我们需要将images、uploadImage, removeImage这些属性封装在hooks中操作,并将这些方法暴露出来 使用的方式,可以参考如下,可以声明不同别名进行多次引用

js 复制代码
// 图片上传
const { images, uploadImage, removeImage } = useImageUpload((res) => {
	// 重置选中图片索引
	currIdx.value = -1;

	updateGif(res.files[0]?.url, TAG_NAME.image);
});

// 多图上传
const {
	images: multiImages,
	uploadImage: uploadMultiImage,
	removeImage: removeMultiImage,
} = useImageUpload((res) => {
	// 重置选中图片索引
	currIdx.value = -1;

	updateGif(res.files[0]?.url, TAG_NAME.imageMulti);
});

// 轮播图上传
const {
	images: swiperImages,
	uploadImage: uploadSwiperImage,
	removeImage: removeSwiperImage,
} = useImageUpload((res) => {
	// 重置选中图片索引
	currIdx.value = -1;

	updateGif(res.files[0]?.url, TAG_NAME.swiper);
});

若是需要上传成功后,将信息回传到自定义的回调方法中,可如上useImageUpload,传入一个成功回调方法做处理。

hooks图片上传

js 复制代码
// 图片上传
export function useImageUpload(uploadSuccess, opts = { rename: true }) {
	const images = ref([]);

	const uploadImage = (file) =>
		new Promise((resolve) => {
			upload(Array.isArray(file) ? file : file.raw, opts)
				.then((res: PutObjectResult[] | PutObjectResult) => {
					const response: { files?: { url: string; name: string }[]; url?: string } = {};
					if (Array.isArray(res)) response.files = res.map((v) => ({ url: v.url, name: v.name }));
					else response.url = res.url;

					uploadSuccess?.(response, images);
					resolve({ status: 'success', response });
				})
				.catch((res) => {
					resolve({ status: 'fail', error: '上传失败', res });
				});
		});

	const removeImage = (index) => {
		images.value.splice(index, 1);
	};

	return {
		images,
		uploadImage,
		removeImage,
	};
}

这段代码定义了一个名为useImageUpload的自定义Vue Composition API hook。该hook接受一个uploadSuccess函数作为参数,以及一个可选的opts对象参数。

代码中的upload为调用上传接口逻辑所封装的方法,可根据各自项目的情况做相应的封装。

useImageUpload函数内部,首先创建一个images响应式引用ref([]),用于存储上传成功的图片列表。

然后定义了uploadImage函数,用于处理图片上传操作。该函数接受一个文件(或文件数组)作为参数,并返回一个Promise对象。在函数内部,调用了一个名为upload的上传函数,传入文件参数和opts选项。该upload函数可能返回一个PutObjectResult对象,或者一个PutObjectResult对象数组。

根据上传结果的不同,构建了一个response对象,该对象包含上传成功的文件的URL和名称。如果上传结果是一个数组,将每个文件的URL和名称保存在response.files属性中,否则将文件的URL保存在response.url属性中。

然后通过调用uploadSuccess函数,将response对象和images列表传递给外部组件进行处理。最后通过Promise对象的resolve方法返回一个包含上传结果的对象,包括状态(successfail)、可能的错误信息和上传结果本身。

最后,定义了removeImage函数,用于从images列表中删除指定索引的图片。

最后,返回一个对象,该对象包含了images列表、uploadImage函数和removeImage函数,供外部组件使用。

相关推荐
k09332 分钟前
sourceTree回滚版本到某次提交
开发语言·前端·javascript
EricWang135823 分钟前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
September_ning23 分钟前
React.lazy() 懒加载
前端·react.js·前端框架
web行路人33 分钟前
React中类组件和函数组件的理解和区别
前端·javascript·react.js·前端框架
超雄代码狂1 小时前
ajax关于axios库的运用小案例
前端·javascript·ajax
长弓三石1 小时前
鸿蒙网络编程系列44-仓颉版HttpRequest上传文件示例
前端·网络·华为·harmonyos·鸿蒙
小马哥编程1 小时前
【前端基础】CSS基础
前端·css
嚣张农民1 小时前
推荐3个实用的760°全景框架
前端·vue.js·程序员
周亚鑫2 小时前
vue3 pdf base64转成文件流打开
前端·javascript·pdf
落魄小二2 小时前
el-table 表格索引不展示问题
javascript·vue.js·elementui