vue3自定义图片上传控件(图片上传+图片回显+定义组件宽高)

本文介绍如何在前端开发中自定义一个图片上传控件,包括上传、图片回显、文件格式限制和上传数量控制,使用Vue.js实现并展示了相关代码和使用示例。
摘要由CSDN通过智能技术生成

        图片上传在平常前端开发中非常常见,插件市场上也有一些上传图片控件,但是有时候控件并不能达到自己想要的效果,所以有时候需要自己定义一个上传插件,下面就是一个简单的自定义上传控件;主要功能就是一个上传还有图片回显的功能,以及定义上传文件的格式和文件的输出功能

<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>

效果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二九筒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值