前言
上节回顾
上一小节中,我们添加了Vue-router的路有数据,这些数据都将是后续实战课程中的真实路由数据了。同时引入了ElementUI的el-menu做为左侧菜单的组件,但本专栏的特点就是遇到第三方功能和组件,自己尽量也要实现一遍,所以,在文章末尾又自己实现了一个tg-menu的组件。如果还不是很明白上下文的同学,可以回过头去看上一节的内容:使用Vue+Vue-router+el-menu实现菜单功能实战
本节介绍
本小节已经是专栏的第11篇博客了,这一节本来是准备开始做图书信息上传的,但考虑到图书信息上传中,有个图片上传的功能点,需要单独抽出一节来说。所以,这一节我们主要是围绕着Vue项目中,通过FormData + axios来实现单个图片上传的功能。
相信你读完本小节,会发现,狗哥这篇文章里,或许不至有图片上传哦。
目录
前言
一、DOM内容的添加
1. 上传按钮和图片预备容器
2. DOM内容说明
3. 数据依赖的添加
二、上传事件说明
1. 上传事件准备
2. 上传事件说明
三、axios上传零件
1. 引入 uploadFile 上传方法
2. 添加 uploadFile 实现代码
3. 添加url管理
四、实现效果展示
1. 上传前
2. 上传请求
3. 上传后预览
五、本小节的周边
一、DOM内容的添加
在Vue中,说DOM的添加总感觉有点别扭,因为我们所书写的HTML DOM部分,是放置在template模板里的,而这里的模板内容离真实的DOM其实还有很多步骤。不过这里先略过这些,我们就以DOM为例。
1. 上传按钮和图片预备容器
在真实的项目中,用户点击的必定不是那个比较丑陋的input file组件,而是提供一个对用户非常友好的上传按钮。然后再放置一个DIV元素,用来预备存放上传成功后的图片,以达到预览的效果。
本小节暂时不用真实的业务组件来开发,先做一个小例子,一旦做成了,下一节图书信息上传就可以直接使用了。打开 /views/HelloWorld.vue 文件,书写以下DOM代码:
<el-button @click="uploadImage">上传图片</el-button>
<p>展示图片:<p>
<div style="width: 300px;height: 300px;border: 1px solid #CCC;">
<img :src="upImage" v-if="upImage" style="width: 300px;height: 300px;" />
</div>
<input ref="imgFile" type="file"
name="file" accept="image/png,image/gif,image/jpeg,image/jpg"
@change="go2UploadImg($event)" style="display: none;">
2. DOM内容说明
- el-button做为用户点击的“上传按钮”;
- DIV元素用来预备预览存放上传后的图片;
- img元素,我们用v-if=“upImage”做为显示判断,如果不做判断,在上传图片前会是一个叉叉的错误图片;
- input type="file"组件是HTML原生的Input组件,也是图片上传中重要的一个环节,用来选取本机系统中的图片
- 一般用户不直接点击input type="file"的组件,而是采用点击正常按钮,点击的同时主动触发上传组件,而后通过change事件做上传实现;
- accept属性表示可上传图片的类型,本例中可选择系统中png gif jpeg jpg这4类图片
3. 数据依赖的添加
新学习Vue的小伙伴可能还不太习惯,什么data数据,什么数据依赖,什么双向绑定,就不能说人话吗?的确如此,越接触破词越多,总是有那么多人喜欢造词。
好吧,说远了,我们上面说到img元素在还没有赋值的时候,会是叉叉,很不友好。所以添加了v-if="upImage"的判断。这里的upImage就是依赖于数据渲染的变量,而说到数据依赖,要想到Vue组件中下面这处代码,data函数中的数据就是所谓的数据依赖
二、上传事件说明
1. 上传事件准备
图片上传是一种行为,是一系列事件。而我们上面说,要通过点击“上传图片”按钮,去触发type="file"的原生组件,而原生组件被触发上传的重点在于change事件,这里注意,click事件只是去触发选择,说白了就是通过代码悄悄的触碰一下上传组件,代码如下
methods: {
uploadImage() {
this.$refs.imgFile.click();
},
go2UploadImg(e) {
const file = e.target.files[0];
const formData = new FormData();
formData.append("file", file);
uploadFile(formData).then((res) => {
this.upImage = res.data;
}).catch(() => {
console.log('图片上传异常,请联系技术人员');
})
}
}
2. 上传事件说明
uploadImage方法中,我们采用refs的方式获取type="file"组件,并且使用click的方式,触发组件的选择功能;
而被处罚的change事件go2UploadImg,才是重点所在。我们通过new FormData对象,在对象中将图片文件信息存进去,做为入参,调用接口进行上传。
三、axios上传零件
因为之前的章节,把axios功能解耦封装的过程已经说过了,而且项目搭建之初做一个很好的整理,对项目实战过程也是事半功倍的。
1. 引入 uploadFile 上传方法
在/views/HelloWorld.vue 文件中,引入uploadFile方法,用于业务组件中上传调用,代码如下:
import { uploadFile } from '@/api/uploadImage.js';
2. 添加 uploadFile 实现代码
新建 /src/api/uploadImage.js文件,这里是 uploadFile 方法的具体实现,而刚才HelloWorld.vue中是业务组件的引用,这里要区分开,代码如下:
import request from '../utils/httpRequire.js';
import { URLS } from '../config/httpUrl.js';
// 上传图片
export function uploadFile(data) {
return request({
url: URLS.upFile,
method: 'post',
data,
});
}
api目录下的文件,之前的章节说过,会做一些ajax上传的具体实现,而需要注意的几点就是:
- request 的引入,这里因为httpRequire.js已经实现完成了,保证每次新建实现文件,引入就好了
- URLS,是对请求url做了一个统一的管理,每个ajax请求会不一样;
- 整理过后的data入参数据也很方便,直接在业务组件中整理好json数据就可以了
3. 添加url管理
打开 /src/config/httpUrl.js 文件,添加新的上传接口url即可,代码如下:
import { HPPT_IP } from "./httpIp";
export const URLS = {
testPost: HPPT_IP + '/admin/book', // post测试路径
testGet: HPPT_IP + '/admin/book', // post测试路径
login: HPPT_IP + '/auth/login', // 登录接口
logout: HPPT_IP + '/auth/logout', // 登出接口
upFile: HPPT_IP + '/upload/image', // 上传图片
}
四、实现效果展示
1. 上传前
上传前,是一个上传按钮,一个预备DIV元素,如图:
2. 上传请求
上传过程中headers有个关键的参数tgCsrfToken,用于判断当前用户是否处于登录状态
3. 上传后预览
上传后,服务端已经将图片存储起来,并且把存储的服务器图片链接返回来了,刚才我们在代码中用了 this.upImage = res.data; 应该还记得吧。到这里,我们这一节的内容就算成功结束了。
五、本小节的周边
依照惯例,我们在文章末尾提出一些关于本文的思考题,这些题和文章内容一样重要。而且这些思考题很有意思,每隔一段时间再回过头来看得时候,总会有新的想法,新的解释,提醒自己再不断地前行着
- 如果让你设计一个图片上传组件,封装起来,你准备如何做?
- 你觉得把一个图片存到数据库里,应该怎么存?
- FormData有什么用?请说出自己的理解
- 如果不用axios上传图片,用jQuery来做呢,怎么做?
- 如何实现多图片上传?
感谢天哥(天哥主页)提供好用的接口,而且天哥的《SpringBoot+Vue前后端分离项目实战》专栏已经积累了25篇实战博客了,看来我该追赶一下了。
转眼间,又快要端午节了,这次放假后,就得再等100天才能再放假了。有时候想时间过得快一些,期盼假期,有时候想时间流逝的慢一些,让自己的青春多停留一下。很纠结,但我们何尝又不是经常在纠结中磨炼,在纠结中成长呢。祝大家端午节快乐吧!我为大家准备了非常有意思的投票,相信不会让你失望的