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

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()即去新建文章页面反正此时都登录了

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何在Idea离线情况下安装vue.js插件

亲践有效&#xff0c;步骤如下: 1. 互联网环境登陆vue.js官网(Vue.js - IntelliJ IDEs Plugin | Marketplace)。 2. 然后先确定你的IDEA的版本&#xff1a;在你IDEA的安装文件中找到product-info.json&#xff0c;里面的buildNumber记录着你IDEA的精确版本号&#xff0c;根据…

ROS2系统与px4通信测试

参考文章&#xff1a; No communication with ROS2 using MicroXRCEAgent with px4 board ROS2官方安装及测试程序 概要 新安装的ROS2与PixHawk开发板进行通信。 操作步骤 启动示例程序&#xff0c;在&#xff5e;/ws_sensor_combined/src路径下执行&#xff1a; ros2 l…

【Image captioning】基于检测模型网格特征提取——以Sydeny为例

【Image captioning】基于检测模型网格特征提取——以Sydeny为例 今天,我们将重点探讨如何利用Faster R-CNN检测模型来提取Sydeny数据集的网格特征。具体而言,这一过程涉及通过Faster R-CNN模型对图像进行分析,进而抽取出关键区域的特征信息,这些特征在网格结构中被系统地…

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…

云服务器和物理机该怎样分别呢

随着网络的不断发展&#xff0c;服务器的类型也在以不同的方式更新。现在云服务器的兴起占据了很大一部分市场&#xff0c;物理机的市场份额受到了很大的冲击。物理机和云服务器有什么区别&#xff1f;如何选择适合自己需求的&#xff1f;虽然物理服务器和云服务器都是服务器&a…

如何部署TDE透明加密实现数据库免改造加密存储

安当TDE&#xff08;透明数据加密&#xff09;实现数据库加密的步骤主要包括以下几个部分&#xff1a; 准备安装环境&#xff1a;确保操作系统和数据库环境已经安装并配置好&#xff0c;同时确保具有足够的权限来安装和配置TDE透明加密组件。下载安装包&#xff1a;从官方网站…

银河麒麟V10桌面版分区分析

前言&#xff1a;本文只讨论gpt分区uefi引导形式 &#xff0c;了解分区方案的目的是方便恢复&#xff0c;还原&#xff0c;扩容等&#xff0c;普通用户使用无需了解这些细节。 先回顾分析windows和ubuntu默认分区用做对比 1、windows11默认分区 win11分区&#xff0c;如上图&am…

如何去除字符串两侧的空白字符?

TRIM函数会去掉字符串左侧和右侧的空格&#xff0c;语法是&#xff1a;TRIM(字符串) excel中&#xff0c;TRIM函数能去掉字符串左侧和右侧的空格&#xff0c;它的ASCII码是32。 以下设定一个字符串组合&#xff0c;它的第一个字符中空格&#xff0c;最后一个字符是换行符 &q…

WSL2-Ubuntu(深度学习环境搭建)

1.在Windows的WSL2上安装Ubuntu 流程可参考&#xff1a;https://www.bilibili.com/video/BV1mX4y177dJ 注意&#xff1a;中间可能需要使用命令wsl --update更新一下wsl。 2.WSL数据迁移 按照下面流程&#xff1a;开始菜单->设置->应用->安装的应用->搜索“ubun…

网络安全法中关于网络信息的保护和监管,有哪些规定?

网络安全法作为我们数字时代的重要法律保障&#xff0c;对于网络信息的保护和监管有着明确且详细的规定。这些规定不仅体现了国家对于网络安全的重视&#xff0c;也为我们每个人在数字世界中提供了坚实的法律屏障。 首先&#xff0c;我们来看一个关于网络运营者主体责任的案例。…

软件工程期末复习(9)数据流图

数据流图 结构化分析方法&#xff1a; 结构化分析方法最初由Douglas Ross提出&#xff0c;由DeMarco推广&#xff0c; 由Ward和Mellor以及后来的Hatley和Pirbhai扩充&#xff0c;形成了今天的结构化分析方法的框架。 结构化分析方法的分析模型&#xff1a; 核心&#xff1a;数…

springboot实现文件防盗链设计

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 个人IP&#xff1a;shigen &#x1f44b;&#x1f44b;&#x1f44b;hello&#xff0c;伙伴们好久不见&…

IO系列(四) - RandomAccessFile 类解读

一、摘要 RandomAccessFile 类&#xff0c;也被称为随机访问文件类。 RandomAccessFile 可以说是 Java 体系中功能最为丰富的文件操作类&#xff0c;相比之前介绍的通过字节流或者字符流接口方式读写文件&#xff0c;RandomAccessFile 类可以跳转到文件的任意位置处进行读写数…

开源连锁收银系统哪个好

针对开源连锁收银系统的选择&#xff0c;商淘云是一个备受关注的候选。商淘云以其功能丰富、易于定制和稳定性等优势&#xff0c;吸引了众多企业和开发者的关注。下面将从四个方面探讨商淘云开源连锁收银系统的优势&#xff1a; 首先&#xff0c;商淘云提供了丰富的功能模块。作…

CNN卷积神经网络初学

1.为什么要学CNN 在传统神经网络中&#xff0c;我们要识别下图红色框中的图像时&#xff0c;我们很可能识别不出来&#xff0c;因为这六张图的位置都不通&#xff0c;计算机无法分辨出他们其实是一种形状或物体。 这是传统的神经网络图&#xff0c;通过权重调整神经元和神经元…

C++学习一(主要对cin的理解)

#include<iostream> int main() {int sum 0, value 0;//读取数据直到遇到文件尾&#xff0c;计算所有读入的值的和while (std::cin >> value){ //等价于sumsumvaluesum value;}std::cout << "Sum is :" << sum << std::endl;sum …

OPC-UA open62541 C++测试代码

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 这是之前写的open62541测试代码…

机器人计算力矩控制

反馈线性化&#xff1a; 反馈线性化是一种控制系统设计方法&#xff0c;其目标是通过状态空间的坐标变换和控制变换&#xff0c;使得非线性系统的输入-状态映射或输入-输出映射反馈等价于线性系统。这样&#xff0c;就可以应用线性系统的控制理论来实现非线性系统的控制。在机…

【Redis】数据类型

Redis数据类型&#xff08;5 3 1&#xff09; 五种基本数据类型 String字符串 特点 二进制安全&#xff0c;可以包含任何数据&#xff0c;如数字&#xff0c;字符串&#xff0c;jpg图片或者序列化的对象 应用场景 缓存&#xff1a; redis作为缓存层&#xff0c;mysql做持…

Java项目:基于ssm框架实现的房屋租售网站管理系统(房屋租赁和房屋出售一体)(B/S架构+源码+数据库+毕业论文+开题+任务书)

一、项目简介 本项目是一套基于ssm框架实现的房屋租售网站管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、…