图片上传在平常前端开发中非常常见,插件市场上也有一些上传图片控件,但是有时候控件并不能达到自己想要的效果,所以有时候需要自己定义一个上传插件,下面就是一个简单的自定义上传控件;主要功能就是一个上传还有图片回显的功能,以及定义上传文件的格式和文件的输出功能
<template>
<div class="uploadImg" :style="{'--width':uploadBoxWidth + 'px','--height':uploadBoxHeight + 'px'}">
<div class="image" v-show="imgUrl.length!=0" v-for="item,index in imgUrl" :key="index">
<img class="imgStyle" :key="index" :src="item" />
<div class="delStyle">
<el-icon size="15" style="color: red;" @click="cleanImg(item)"><Delete /></el-icon> <!--删除图标,可自定义 -->
</div>
</div>
<div class="upload" v-show="imgUrl.length<limit">
<el-icon class="icon" size="40"><Plus /></el-icon> <!--删除图标,可自定义 -->
<input class="inputStyle" type="file" :multiple="props.multiple" @change="getImgList">
</input>
</div>
</div>
</template>
<script setup>
import { getCurrentInstance, ref, defineExpose } from 'vue';
const {proxy} = getCurrentInstance()
const props = defineProps({
type: { //上传图片类型
type: Array,
default: ['jpg','png','jpeg','PNG','JPG','JPEG']
},
limit: { //限制上传数量
type: Number,
default: 1
},
multiple: { //是否支持多选
type: Boolean,
default: false
},
uploadBoxWidth: { //定义上传组件宽度
type: Number,
default: 100
},
uploadBoxHeight: { //定义上传组件高度
type:Number,
default: 100
}
})
const imgUrl = ref([])
const imgData = ref([])
/**
* 组件方法(供给父组件使用)
*/
const cleanData = () => {
imgData.value = [];
imgUrl.value = [];
}
/**
* 导出组件方法
*/
defineExpose({
cleanData
})
/**
* 图片处理
*/
function getImgList(e) {
let imgList = Array.from(e.target.files)
let URL = window.URL || window.webkitURL; //生成游览器url
imgList.forEach(e=>{
if(props.type.indexOf(e.name.split('.')[1])!==-1) { //判断上传类型
if (imgUrl.value.length<props.limit) { //判断上传数量
let imgURL = URL.createObjectURL(e);
imgUrl.value.push(imgURL);
imgData.value.push(e);
}else {
proxy.$ElMessage({ //超过上传数量限制提示消息;这个是消息插件,用自己的即可
type: "warning",
message: `上传数量最多${props.limit}张!`
})
}
}else {
let text = "";
props.type.forEach(e=>{text += e + '、'})
text = text.slice(0,-1)
proxy.$ElMessage({
type: "warning",
message: `上传文件仅支持${text}格式`
})
}
})
proxy.$emit("imgData", {"Data":imgData.value,"Url":imgUrl.value}); //传输数据给父组件
}
/**
* 删除图片
*/
function cleanImg(e) {
let imgDataIndex = imgUrl.value.indexOf(e,0)
imgUrl.value=imgUrl.value.filter(item=>item!=e)
imgData.value.splice(imgDataIndex,1);
proxy.$emit("imgData", {"Data":imgData.value,"Url":imgUrl.value}); //传输数据给父组件
}
</script>
<style lang="scss">
/**
全局定义宽高,为后面元素计算提供宽高
*/
$width: var(--width);
$height: var(--height);
.uploadImg {
width: $width;
height: $height;
display: flex;
.image {
width: 100%;
height: 100%;
position: relative;
.delStyle {
width: calc(100% - 4px);
height: 22px;
position: absolute;
top: calc($height - 22px);
left: 2px;
display: none;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
background: #423d3d;
}
.imgStyle {
width: calc($width - 4px);
height: calc($height - 4px);
border-radius: 5px;
margin: 2px;
}
}
.image:hover .delStyle {
display: flex;
align-items: center;
justify-content: center;
}
.upload {
width: calc($width - 6px);
height: calc($height - 6px);
margin: 2px;
border: 1px dashed #000000b9;
border-radius: 5px;
position: relative;
.inputStyle {
width: $width;
height: $height;
opacity: 0.0;
z-index: 1;
}
.icon {
position: absolute;
left:calc(100% / 2 - 20px);
top: calc(100% / 2 - 20px);
z-index: 0;
}
}
}
</style>
使用方法:
把组件引入到要使用页面或者直接在main.js内设置为全局通用组件都行
<template>
<div>
<UploadImg ref="uploadImg" :limit="1" :multiple="false" :type="types" :uploadBoxWidth ='100' :uploadBoxHeight='100' @imgData="getImgData" />
</div>
</template>
<script setup>
import UploadImg from '@/components/UploadImg.vue';
const types = ref(["JPG","PNG","JPEG","png","jpg","jpeg"])
function getImgData(e) {
console.log(e)
}
</script>
效果: