web端项目中有一个上传图片的功能,但是element-ui提供的上传插件都不能满足的我的需要,dropzone也因为我们框架封装的原因,在重置和初始化时都有一些问题。在研究dropzone的问题上花费了很多时间,最后也没解决,就索性自己写了一个。
整理思路
功能方面:
1、上传图片,那肯定是input,type=“file”
2、获取图片,监听input的change事件
3、拿到图片上传
页面样式:
1、展示一个虚线框,没有图片时中间显示一个+号,点击选择图片;
2、有图片时展示图片,鼠标悬浮在图片上方时显示移除按钮,否则不展示移除按钮
代码如下:
<template>
<div class="dropzone">
<input ref="uploadInput"
type="file"
name="file"
value=""
accept="image/gif,image/jpeg,image/jpg,image/png"
@change="selectImg($event)">
<div :class="operationShow?'operation-div':'operation-div hide'">
<img :src="defaultImg">
<span class="remove"
@click="remove">移除</span>
</div>
<div :class="operationShow?'txt hide':'txt'">
+
</div>
</div>
</template>
<script>
export default {
props: {
url: {
default: "",
type: String
},
imgSrc: {
default: "",
type: String
},
autoUpload: {
default: true,
type: Boolean
}
},
data()
{
return {
operationShow: false,
uploadFile: "",
defaultImg: process.env.BASE_API + "/service-admin/" + this.imgSrc
};
},
watch: {
imgSrc(newsVal, oldVal)
{
this.init(newsVal);
}
},
mounted()
{
this.init(this.imgSrc);
},
methods: {
//选择图片
selectImg(e)
{
const imgFile = e.target.files[0];
if (imgFile)
{
this.uploadFile = imgFile;
let reader = new FileReader();
reader.readAsDataURL(imgFile);
reader.onload = (event) =>
{
this.defaultImg = reader.result;
this.operationShow = true;
if (this.autoUpload)
{
this.upload();
}
};
}
},
upload()
{
//将图片转成FormData类型数据
let formData = new FormData();
formData.append("file", this.uploadFile);
///通知父级上传图片
this.$emit("uploadImg", formData);
},
remove()
{
// 图片设为空
this.defaultImg = "";
// 隐藏图片层,展示选择图片层
this.operationShow = false;
//通知父级移除图片
this.$emit("removeImg");
},
init(data)
{
//图片不为空时,显示图片层并展示图片,input层隐藏
if (data !== undefined && data !== "" && data !== null)
{
this.operationShow = true;
this.defaultImg = process.env.BASE_API + "/" + data;
}
else
{
//图片为空时,不显示图片层,显示input层
this.defaultImg = "";
this.operationShow = false;
}
}
}
};
</script>
<style rel="stylesheet/scss" lang="scss" >
@mixin base{
position: absolute;
top: 5%;
height: 100%;
width: 100%;
}
.dropzone{
position: relative;
height: 200px;
max-width: 200px;
width:100%;
border: 1px dashed #ccc;
box-sizing: border-box;
input{
@include base;
opacity: 0;
z-index: 10;
}
.operation-div{
@include base;
z-index: 100;
text-align: center;
img{
width: 80%;
height: 80%;
}
&:hover>.remove{
display: block;
}
.remove{
display: block;
height: 10%;
width: 100%;
display: none;
text-align: center;
cursor: pointer;
}
.remove:hover{
color: #409EFF;
}
}
.txt{
position: absolute;
width: 100%;
height: 30px;
font-size: 40px;
line-height: 30px;
top: 50%;
transform: translateY(-50%);
text-align: center;
color: #aaa;
z-index: 1;
}
.hide{
display: none;
}
}
</style>
在父组件中使用:
<el-form-item
label="图片"
prop="pic">
<form-upload-image
:auto-upload="true"
:img-src="form.data.pic" // form表单的数据
@uploadImg="uploadImg"
@removeImg="removeImg"/>
</el-form-item>
// 上传图片
uploadImg(formData)
{
//手动校验图片输入框
this.$refs["dataForm"].validateField("pic");
//使用axios上传图片,repo是自己写的axios拦截器
new Repo({
url: 'url',
method: "post",
data: formData,
headers: { "Content-Type": "multipart/form-data" }
}).then((response) =>
{
// 上传成功,清空校验信息
this.$refs["dataForm"].clearValidate("pic");
//修改form data数据
this.form.data.pic = response.data[0];
});
},
// 移除图片
removeImg()
{
//修改form data数据
this.form.data.pic = "";
//手动校验图片输入框
this.$refs["data-form"].$refs["default"].validateField("pic");
}