vue3专栏项目 -- 六、上传组件(上)

news2024/9/21 20:55:06

1、上传组件需求分析

我们还需要新建和展示文章,新建文章自然是发送post请求,同时在post中自带对应的数据,展示文章就是根据id取出已有的数据并且展示出来。

这里有一个难点就是上传组件,上传文件是App应用中最基本的需求,在Ajax出现之前,我们一般都使用一个简单的input框来实现这个上传的流程,把它的type设置成file,把from提交以后都交给后端处理。

自从有了ajax出现了以后,JS有了异步发送请求的能力,我们可以更方便的在页面不跳转的情况下完成文件的上传,同时还能获得很好的可视化效果,比如说传的百分比、图片的预览、最终的状态等等

整个流程,一开始我们应该有能力让用户去检查这个图片的格式或者大小的,我们会提供一个属性叫beforeUpload,它是一个function,让用户去检查这个文件的一些具体的需求;然后通过以后,这个时候这个组件就会向外反射一个uploading这样一个事件;然后上传成功以后就会触发filrUploaded这个事件,或者出现错误就会触发uploadedError这个事件。这些事件对于用户来说非常重要,他们很需要知道这些事情是什么样的时间发生的,然后可以做取得额外的工作,比如说beforeUploaded我们进行上传前的检查如文件类型/大小等等,或者在最终上传失败的时候我们可以弹出一些额外信息等等,这些都是事件给我们带来的魔力,除了这些事件以外,自定义也是我们的一大看点,我们的用户应该可以使用template来自定义一些显示的内容,比如说我们一开始上传区域长成什么样可以是一大片也可以是一个button等,上传中显示什么图标什么文字,上传完毕以后要显示什么样的数据,这些我们应该是可以完全自定义的

通过流程这么分析,我们大致得出组件大致应该有些什么,如下

它应该有一个action,代表着我们要把这个请求发送到后端哪里去处理;然后应该有一个function即beforeUploaded去完成一些上传前的校验;之后就是3个要触发的事件,uploading(点击上传按钮后)、fileUploaded(上传成功后)、uploadedError(上传失败后);除了这些我们还要支持自定义模板,默认就是一开始它长什么样,我们这里是一个button,然后我们可以添加这个template,这个template分为uploaded的即上传前的模板和loading的即上传中的模板

发送异步请求是上传组件的一个核心内容,那么接下来我们就谈谈使用axios来发送异步请求怎样完成文件的上传这个流程

2、上传文件的两种实现方式

接下来我们来了解上传文件的原理

我们先从form提交的时候谈起,既然要上传文件,当然就要选择文件,那么就可以选用如下

<input type="file">的标签,这时候它就会渲染出一个可以选择文件的对话框;那么当文件选择完毕以后,我们有两种方式上传,一个是使用传统的form submit即表单提交的方式;第二种是使用JavaScript发送异步请求的方式,这是我们着重要实现和理解的方法;

(1)如下我们了解一下第一种使用传统的form submit即表单提交的方式的流程

如下例子,我们选择文件然后点击submit的时候它就会运行form的默认行为,带input当中的数据,然后直接发送到一个特定的HTTP request请求到axios 的url,我们这里axios是/api/upload即会把input中的数据post到后端API为upload的地方中去,然后server端接到这个请求以后会做对应的处理,并且返回结果,这是一种典型的request到server的形式。这里要特别注意,我们这个表单一般于发送普通消息的表单,不同的地方就在于我们发送了文件,文件和普通的字符串不同,文件属于一种二进制的格式,所以我们需要设置这个enctype="multipart/form-data",注意你要上传文件或者你表单发送的有二进制的文件,那么就最好设置这种enctype="multipart/form-data"格式,因为表单的默认格式不支持二进制数据,所以需要设置成支持二进制数据的

我们选择了文件后,点击submit可以看到后端拿到这个内容以后就会做出对应的响应,它会返回如下图片地址

我们的接口文档中也提供了对应的接口

(2)使用JavaScript做file类型的表单上传功能

了解了这些之后,我们就可以使用JavaScript来发送异步上传文件的post请求了,提交form其实也就是发送http请求,那么使用JavaScript发送异步当然有更好的体验了,其实它的过程也是万变不离其宗的,也是用它来模拟表单的发送http请求

我们来新建文章页面来尝试一下,如下

然后我们尝试一下上传功能,如下我们点击上传某图片后,上传成功后它就打印出上传成功的信息

从上面可以看到,使用JavaScript发送异步请求的方式和form提交的过程是非常相似的,只不过是用javascript模拟原生form的提交方式

3、Uploader组件 第一部分 -- 上传组件流程

就和上面一样,完成那个流程即可

(1)首先创建一个按钮,使得点击这个按钮就执行file类型的input的点击事件即弹出选择文件的弹窗

如下,创建一个上传组件叫Uploader.vue

复习一下:还记得怎么在setup中拿到一个dom节点吗,通过ref咋拿来着,如下首先在标签里通过加上ref="fileInput",然后const fileInput = ref<null | HTMLInputElement>(null),然后直接通过fileInput.value即可拿到这个fileInputDOM节点了

form那个方式是有一个input框,然后右边有一个submit按钮,我们想有一个按钮,然后点击这个按钮就触发file类型的input框,即想只展现出一个按钮,这个按钮的点击事件中就触发这个file input即form上传功能。

怎么做,我们就如下设置一个button,也设置一个file类型的input,但是让这个input隐藏即可,然后button的点击事件中去获取这个input的DOM节点,拿到input节点后接着去触发input的点击事件,即form中的那个submit的点击事件(这个点击事件就会去让你挑选文件这样子)。这样就实现了页面中展示一个点击上传的按钮,然后你点击这个按钮,就会自动去触发类型为file的input的点击事件,从而就会展示出让你选择文件的弹窗

接下来我们来添加属性

我们要接收一个action,这个action是接收发送请求的地址,而且是必选项是必须填的

(2)接下来就是上面说的经典的上传过程

这里有个问题就是我们要根据不同的上传阶段,展示不同的元素,所以我们需要有一个字段来指示一下状态如下,然后我们就开始做状态变化后触发的函数即handleFileChange函数

在这个函数中,我们做的就是如下获取input这个DOM节点,这是为了我们在选择文件的时候去获取这个input的files属性,因为我们选择文件后这个input会带上files属性,这个属性中就是我们选择的那些文件们。我们获取到我们选择的文件后,首先去修改上传的状态,如下

这个e.target即事件对象就是这个input

我们选择文件后,这个input就会加上这个files属性,这个属性即currenTarget.files打印出来可以看到就是我们选择的那些文件,是一个列表list

然后继续,获取到我们选择的文件后,我们把这个files变成一个Array,因为这个files是一个list并不是一个Array,我们用Array.form()来转换成Array,是为了后面取它第一个。

然后创建一个form表单数据的属性,怎么创建就通过new FormData() 从而创建一个Form表单数据属性;然后把files的第一个数据给新建的这个FormData;FormData表单中有数据了,那么就可以进行post请求了,这个post请求中要传三个参数,一个是url,一个是传的数据,一个是headers(要写成如下这个才可以接收二进制文件);最终处理请求的结果,通过.then() 接请求成功的结果然后进行如下处理,通过.catch() 接请求失败的结果然后进行如下处理,最后那个finally是无论成功还是失败都进行的函数,因为我们选择了文件了嘛,所以input中的value被这个文件占了,你得先清空,下次再选择时才不会出错

(3)整个上传流程总结:

我们的template中有button和file类型的input(给隐藏input),然后我们是通过点击这个button去触发该input的click点击事件,这个点击事件就会弹出让你选择文件的弹窗。

然后此时input在变化即change,说明此时在上传文件,那么我们就给个change事件,这个事件是上传的重点

在这个change事件中,我们要做的流程就是:获取上传的文件-->建表单数据-->发起请求,把选择的文件传给对应API

首先,获取这个input这个dom节点(因为选择文件后input会增加一个files属性,这个属性中就是我们选择上传的文件列表),获取这个input就是为了获取我们选择上传的文件

然后,拿到要上传的文件后,新建一个表单数据属性,并且给这个属性files的值(因为post请求中要提交你选择的文件嘛)

①把这个files列表变成Array即数组(这是为了获取列表的第一个文件,我们只能选择一个文件)

②新建一个form表单数据属性,通过new FormData()

③把files中第一个文件数据给新建的这个FormData

最后,发起post请求,处理请求可能的请求成功、请求失败的处理

至此文件已经可以成功上传

过程中有一个小错误:

这里有一个要注意的点,就是发现在setup中说取不到props,要注意,setup(){}的括号中要写上props才能取到props的值,有时候不小心漏了,setup函数,它接收两个参数,一个是props,一个是context

4、Uploader组件 第二部分 -- 不同阶段自定义操作

上面我们完成了上传组件的最基本的流程,现在我们要将这里面的功能慢慢丰富进去

第一大功能就是在不同阶段暴露出一系列的事件,对于用户想在不同阶段进行自定义操作的话就很有用;第二个是自定义模板,用户可以根据需求渲染自己想要的页面

(1)在上传组件前,我们想自定义一个函数在上传之前去检查,比如上传前检查图片是不是JGP格式,是JPG格式才能上传

在上传前我们想要有一些检查的流程即beforeUpload函数,这个检查是怎么检查我们想要自定义式,怎么才能自定义呢,就你使用的地方定这个检查逻辑,在这个上传组件中只调用这个函数即可。

这个函数中应该接收用户选择的文件,然后经过一些列检查,最终返回布尔值,布尔值代表着检查的结果

如下在Uploader组件中

如下在Home.vue中,我们创建自定义检查的这个beforeUpload函数,并且传给uploader组件

即可如下,点击上传比如png的图片,就会出现如下提示

(2)上传成功后和上传失败后,我们想在这两个时候做一些自定义的事情,则如下

如下,定义emits,emits中有file-uploaded表示上传成功时调的函数、file-uploaded-error表示上传失败时调的函数,然后在上传的post请求成功时通过context.emit()去调用对应的函数

从接口文档中,我们可以看到返回的数据都是code、msg、data这样的,所以我们到store中定义一个通用的格式,这样就能享受到TypeScript类型的帮助,如下

然后我们在Home组件中定义这个上传成功的函数以及上传失败的函数,如下

5、Uploader 组件第三部分 -- 自定义模板

(1)使用slot来做自定义模板

我们在Dropdown组件中我们已经见识过自定义模板,它是使用这个slot来完成这个对应功能的,让我们来复习一下,我们使用name slot 来完成不同自定义模板的需求,我们在组件中添加slot,并且加上对应的name属性,然后在使用的时候我们可以使用template标签配合v-slot:name属性来使用,这里面就是你自定义的HTML内容,v-slot也可以简写成一个#

现在要展示3个阶段的界面,所以自然要展示三个slot来放置对应的自定义模板,所以如下我们来修改一下Uploader

如下,把正在上传、上传成功、点击上传都做成一个slot插槽,然后默认没什么的时候它们就是一个个按钮

然后如果这里面插入了东西,比如插入一段<h2>,那么就会替换这个插槽,但是这个h2标题还是有这个button这个按钮功能,如下

插槽名为default时即展示h2的点击上传文本

插槽名为loading时,则展示这个旋转图标

上传完毕后,我们需要在父组件Home.vue中拿到子组件Uploader.vue的一些数据,比如我们上传完毕后想展示出这个图片啥的,为了让组件在slot中访问子组件的某些特性,vue提供我们Scoped Slots就是为了让我们解决这个问题的

(2)使用scoped slot 来解决子组件传值给父组件的问题

看文档,如下,子组件slot标签中可以通过v-bind将一个属性绑定到这个slot上面去,然后我们就可以给父组件中对应标签中加上v-slot="xxx",然后通过xxx.这个属性即可拿到这个属性

如下,在Uploader组件中,我们新建一个ref属性记录请求成功时返回的数据,然后我们在slot中通过v-bind把这个数据传出去,如下

然后到Home组件中使用,如下用v-slot接传过来的值,把传过来的值取名叫dataProps,然后在img中使用如下

如下,上传成功后,图片就展示出来了,这样就实现了在slot中父组件使用子组件的数据的问题

6、改进路由验证系统

接下来我们将上传组件添加到新建文章页面中,但是现在路由跳转还有一些问题,我们先处理这个。

我们刚开始的路由验证流程是如下这样

但是我们发现了有一些问题,就是我们在下拉菜单组件点击新建文章按钮,可以正常跳转到新建文章页面,但是如果此时我们在新建文章页面刷新就会发现会跳转到登录页面,但是我们明明已经登录了呀

这是因为路由中我们还是使用了store.state.user.isLogin来判断的,而点击刷新后store中的数据是都重置回初始值的。所以你登录后isLogin确实从false置为true了,但是你刷新后isLogin就又是为false了,那么就符合这个if判断了,所以就重定向到了登录页面去给你了

但是其实你此时是已经登录状态,而你用store.state.user.isLogin判断就给你错判成了未登录状态,所以首页登录过以后再点击新建文章通过这个链接进行跳转的话就不会有这个问题,这是我们要解决的问题,这里涉及稍微复杂的流程

所以我们要改进一下路由验证系统,让它更完善一些

我们做个流程图,其实我们多的逻辑就是在发送请求这一步,其他的没有什么区别,只不过现在的逻辑比以前复杂了一些

如下,一开始我们判断这个user.isLogin,

如果已登录是true,则判断redirectAlreadyLogin这个参数存不存在,存在则跳转到首页,不存在则继续进行;

如果未登录是flase,那么我们就去判断是否有token,

如果token不存在,则去判断它访问的这个路由是不是需要登录才能访问的,如果不是则继续进行即让他去这个路由的页面,如果是需要登录才能访问的则跳转到登录页面让他先登录;

(前面的和我们之前的一样,我们新添加的逻辑就在这里)如果token存在,也就是说user的isLogin为false但是有token的情况,那么有可能是像上面这种刚刚刷新了isLogin为false但是其实是已登录的状态,也可能是有token但是是之前登录的现在确实还没有登录,有token就说明这个用户刚才或者之前登录过,所以就直接重新发送一次异步fetchCurrentUser请求去登录(这也是常见的,短时间内会自动登录的嘛);然后就如果登录失败就弹出提示回到登录页面让重新登录,如果登录成功则判断是不是要到登录或注册页面,如果是则重定向回首页,如果不是比如是要到新建文章页面那么直接next()即去新建文章页面反正此时都登录了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1680083.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

五丰黎红销量增长的秘诀:一物一码数字化营销开创调味品行业新格局!

根据当今经济环境和未来的发展趋势&#xff0c;传统经济向数字化经济转型的发展方向可以说是大势所趋&#xff0c;如何把握先机&#xff0c;率先迈出数字化转型第一步&#xff0c;可以说是无数传统企业都需要思考的问题。 作为中国调味品行业的佼佼者&#xff0c;五丰黎红踩着时…

如何查看SNMP设备的OID

什么是OID和MIB OID OID 代表对象标识符。 OID 唯一地标识 MIB 层次结构中的托管对象。 这可以被描述为一棵树&#xff0c;其级别由不同的组织分配。MIB MIB&#xff08;管理信息基&#xff09;提供数字化OID到可读文本的映射。 使用MIB Browser扫描OID 我的设备是一台UPS SN…

13、24年--信息系统治理——IT审计

1、IT审计基础 1.1 IT审计定义 无重要的考点,自己读课本了解即可。 1.2 IT审计目的 1)IT审计的目的是指通过开展IT审计工作,了解组织IT系统与IT活动的总体状况,对组织是否实现IT目标进行审查和评价,充分识别与评估相关IT风险,提出评价意见及改进建议,促进组织实现IT目…

TCP(1)

传输层的两大协议是TCP 和 UDP &#xff0c;他们在传输数据的时候起到了不可替代的作用。那么什么是TCP呢&#xff1f; 首先TCP是一个网络传输协议&#xff0c;这个协议保证了可靠的数据传输。TCP是面向字节流的&#xff0c;全双工的&#xff08;也就是通信双方互相发消息&…

单位内部防泄密策略与技术实践

在信息时代&#xff0c;企业内部数据安全至关重要&#xff0c;尤其是涉及核心竞争力的重要文件&#xff0c;员工的不当操作或恶意泄露都可能给企业带来重大损失。本文将从制度建设、技术防护、以及日常管理三个方面入手&#xff0c;探讨如何构建一套行之有效的内部防泄密体系&a…

汇聚荣:拼多多长期没有流量如何提高?

在电商的海洋中&#xff0c;拼多多以其独特的团购模式吸引了众多消费者的目光。然而&#xff0c;随着市场竞争的加剧和消费者需求的多样化&#xff0c;一些商家发现自家店铺的流量持续低迷&#xff0c;销售业绩难以突破。面对这样的挑战&#xff0c;如何有效提升拼多多店铺的客…

大模型算法(零) - Transformer中的细节与实现

讲transformer的文章已经铺天盖地了&#xff0c;但是大部分都是从原理的角度出发的文章&#xff0c;原理与实现之间的这部分讲解的较少&#xff0c;想要了解实现细节&#xff0c;还是要去看代码才行。记录一下自己学习过程中遇见的细节问题和实现问题。 Transformer整体架构 图…

树链剖分详解,看这一篇就够了

前置知识&#xff1a; 树形结构链式前向星(熟练)线段树(熟练)DFS序(熟练)LCA(了解定义) 什么是树链剖分 树链剖分其实有两种&#xff1a;重链剖分和长链剖分。重链剖分就是把儿子节点最重的儿子称为重儿子&#xff0c;把树分成若干条重链&#xff08;如图一&#xff09;&#…

【NR学习一】NR中的带宽、子载波间隔、PRB数量、FFT点数与采样率之间的关系

NR中的带宽、子载波间隔、PRB数量、FFT点数与采样率之间的运算关系 在5G NR&#xff08;New Radio&#xff09;系统设计中&#xff0c;带宽&#xff08;Bandwidth&#xff09;、子载波间隔&#xff08;Subcarrier Spacing, SCS&#xff09;、资源块&#xff08;Resource Block…

汇聚荣科技:如何有效为拼多多店铺引流?

在电商竞争激烈的今天&#xff0c;为拼多多店铺引流是每个店主必须面对的挑战。有效的引流策略不仅能增加店铺曝光度&#xff0c;还能提升转化率&#xff0c;促进销量增长。 一、社交媒体营销 利用微信、微博等社交平台进行推广&#xff0c;可以通过发布产品信息、用户评价和促…

Web3Tools - 助记词生成

Web3Tools - 助记词生成工具 本文介绍了一个简单的助记词生成工具&#xff0c;使用 React 和 Material-UI 构建。用户可以选择助记词的语言和长度&#xff0c;然后生成随机的助记词并显示在页面上 功能介绍 选择语言和长度&#xff1a; 用户可以在下拉菜单中选择助记词的语言&…

【半夜学习MySQL】复合查询(含多表查询、自连接、单行/多行子查询、多列子查询、合并查询等详解)

&#x1f3e0;关于专栏&#xff1a;半夜学习MySQL专栏用于记录MySQL数据相关内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 回顾基本查询多表查询自连接子查询单行子查询多行子查询多列子查询在from子句中使用子查询合并查询 回顾基本查询 下面使用…

设计非递归算法,编程:在二叉排序树中,打印关键码a, b的公共祖先。注:例,若a是b的祖先,则a不算作公共祖先。反之亦然。

二叉排序树&#xff1a; 代码&#xff1a; #include <iostream> using namespace std;// 定义二叉树节点结构 typedef struct BTNode {char show;struct BTNode* left;struct BTNode* right; } BTNode;// 非递归插入节点的函数 BTNode* insertNode(BTNode* root, char k…

Hadoop3:HDFS副本节点选择逻辑讲解

一、副本节点选择&#xff08;机架感知&#xff09; 说明 第一个副本&#xff0c;因为我们的client可能是web页&#xff0c;也可能是shell终端。 如果是web页&#xff0c;则随机选取一个节点&#xff0c;如果是shell终端&#xff0c;则选择当前shell终端所在的节点。 节点距离最…

TiDB学习2:TiDB Sever

目录 1. TiDB Server架构 2. sql语句的解析和编译 2.1 Parse ​编辑 2.2 compile 3. 行转化为KV对(聚簇表) ​编辑4. SQL 读写相关模块 4.1 DistSQL(复杂查询) 4.2 KV(简单查询) 5. 在线DDL相关模块 6. GC机制与相关模块 7. TiDB Server的缓存 8. 热点小表缓存 9. …

财富增长新途径:副业赚钱方法全攻略

探寻财富之路:多元化赚钱途径解析 在追求财富的道路上,每个人都在以自己的方式前行。然而,正如古人所云:“君子爱财,取之有道。”今天,我将为您揭示一些新颖且实用的赚钱途径,希望能为您的财富积累之路注入新的活力。 1、视频内容的创作与分享 在这个视频内容为王的时…

Benedict Evans:Ways to think about AGI思考 AGI 的方法:

​Benedict Evans本文发布于2024 年 5 月 4 日 How do we think about a fundamentally unknown and unknowable risk, when the experts agree only that they have no idea? 当专家们一致认为他们一无所知时&#xff0c;我们如何看待根本上未知和不可知的风险&#xff1f; T…

关于 vs2019 c++20 规范里的 STL 库里模板 decay_t<T>

&#xff08;1&#xff09; 这个模板&#xff0c;在库代码里非常常见。 decay 英文是“衰弱&#xff0c;消减” 的意思&#xff0c;大概能感觉到就是要简化模板参数 T 的类型&#xff0c;去掉其上的修饰符。因为常用且复杂&#xff0c;故单独列出其源码和注释。先举例其应用场景…

JumpServer堡垒机应用(v3.10.8) 下

目录 JumpServer堡垒机简单式部署与管理(v3.10.8) 上-CSDN博客 一. 资产管理 1.1创建资产 1.2 给资产主机创建用户 1.2.1 普通账户&#xff1a; 1.2.2 特权账户&#xff1a; 1.2.3 创建用户 二. 命令过滤 2.1 创建命令组 2.2 创建命令过滤 ​编辑 三. 创建资产授权 …

《Python编程从入门到实践》day29

# 昨日知识点回顾 修改折线图文字和线条粗细 矫正图形 使用内置格式 # 今日知识点学习 15.2.4 使用scatter()绘制散点图并设置样式 import matplotlib.pyplot as plt import matplotlib matplotlib.use(TkAgg)plt.style.use(seaborn-v0_8) # 使用内置格式 fig, ax plt.subpl…