在el-form每个el-form-item在el-pload上传单张图片的时候,选中一张图片展示出图片之后隐藏上传框展示
引用new bing作答:
以下是一个示例代码,展示了如何使用 el-upload 实现在 el-form 中上传并预览单张图片后隐藏上传框的功能。
<template>
<el-form ref="form" :model="form">
<el-form-item label="图片上传">
<el-upload
ref="upload"
class="upload-demo"
:action="uploadUrl"
:show-file-list="false"
:on-success="handleSuccess"
:before-upload="beforeUpload"
>
<el-button slot="trigger" size="small" type="primary">上传图片</el-button>
<img v-if="imageUrl" :src="imageUrl" class="preview-image" />
<el-input v-else class="upload-input" placeholder="请选择文件" readonly />
</el-upload>
</el-form-item>
</el-form>
</template>
<script>
export default {
data() {
return {
form: {
file: null
},
imageUrl: null,
uploadUrl: '/your/upload/url'
};
},
methods: {
beforeUpload(file) {
const isJPG = file.type === 'image/jpeg';
const isPNG = file.type === 'image/png';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG && !isPNG) {
this.$message.error('上传图片只能是 JPG 或 PNG 格式');
return false;
}
if (!isLt2M) {
this.$message.error('上传图片大小不能超过 2MB');
return false;
}
return true;
},
handleSuccess(response, file) {
this.imageUrl = URL.createObjectURL(file.raw);
this.form.file = file.raw;
this.$refs.upload.clearFiles();
}
}
};
</script>
<style scoped>
.preview-image {
max-width: 200px;
max-height: 200px;
margin-top: 10px;
}
.upload-input {
width: 200px;
height: 32px;
margin-top: 10px;
}
</style>
在这个示例代码中,el-upload 组件包含了一个按钮和一个预览图片的区域。当用户选择一个图片上传时,before-upload 方法会检查文件类型和大小是否符合要求,如果通过检查,则会调用 handleSuccess 方法处理上传成功后的响应。在 handleSuccess 方法中,我们通过 URL.createObjectURL 创建了一个预览图片的 URL,将这个 URL 赋值给 imageUrl 变量,并将上传成功的原始文件赋值给 form.file 变量。最后,我们调用 $refs.upload.clearFiles() 方法清除上传队列,隐藏上传框并展示预览图片。
示例代码中的 uploadUrl 变量应该替换为你自己的上传地址。另外,如果你需要在提交表单时一起上传这张图片,请确保在表单提交前将 form.file 一起提交。
可以在el-upload组件的change事件中添加一个判断,如果上传成功,则将上传框隐藏,展示上传成功后的图片。具体实现可以参考以下代码:
<template>
<el-form>
<el-form-item label="上传图片">
<el-upload
action="/upload"
:show-file-list="false"
:on-success="handleSuccess"
:before-upload="beforeUpload"
:file-list="fileList">
<img v-if="imageUrl" :src="imageUrl" style="max-width: 100%">
<el-button v-else>点击上传</el-button>
</el-upload>
</el-form-item>
</el-form>
</template>
<script>
export default {
data() {
return {
fileList: [],
imageUrl: ''
}
},
methods: {
handleSuccess(response, file, fileList) {
this.imageUrl = URL.createObjectURL(file.raw)
this.fileList = fileList
},
beforeUpload(file) {
// 隐藏上传框
this.$nextTick(() => {
const uploadBtn = document.querySelector('.el-upload__input')
uploadBtn.style.display = 'none'
})
}
}
}
</script>
在beforeUpload方法中,通过$nextTick方法确保上传按钮已经渲染完毕,然后获取上传按钮元素,将其display属性设置为none,实现隐藏上传框的效果。在handleSuccess方法中,将上传成功后的图片展示出来,同时更新fileList数组。
提供一套自己封装的组件,支持拖拽上传,点击选择上传。
上传后可以移除或者再次上传。
上传组件:upload.vue
<style lang="scss" scoped>
:deep(.el-button.el-button--small) {
width: 65px;
left: 50% !important;
margin-left: -32.5px !important;
}
.roshi-upload input[type="file"]{
height: 0;
width: 0;
position: relative;
top:-2000px;
left:-2000px;
visibility: hidden;
}
.roshi-uploadArea {
width: 400px;
}
.roshi-uploadArea .imageButton {
position: absolute;
left: 38px;
}
.roshi-uploadArea .imageButton.delete {
top: 40px;
left: 42px;
background-color: transparent;
color: #fff;
border-color: #fff;
}
.roshi-uploadArea .imageButton.again {
top: 84px;
margin-left: 0;
}
.roshi-uploadArea .imageButton.upload {
top: 100px;
}
.roshi-wechat-site-uploadArea .left{
position: relative;
}
.roshi-uploadArea .cover {
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, 0.6);
border-radius: 4px;
}
.roshi-uploadArea .roshi-loading {
margin-top: 40px;
}
.roshi-uploadArea .left {
position: relative;
/* cursor: pointer; */
width: 150px;
height: 150px;
border: 1px solid #e4e9f2;
border-radius: 4px;
background-color: #f7f9fc !important;
/*background-size: 42px !important;*/
text-align: center;
}
.roshi-uploadArea .left .leftText {
position: relative;
top: 64px;
height: 17px;
font-size: 12px;
color: #a6aebc;
line-height: 17px;
}
.roshi-uploadArea .right {
vertical-align: bottom;
padding-left: 20px;
}
.roshi-uploadArea .right p {
font-size: 14px;
color: #cccccc;
line-height: 20px;
}
</style>
<template>
<div class="roshi-upload" :id="uploadId">
<!-- <div class="uploadArea">
拖入上传
</div> -->
<div class="roshi-uploadArea fn0 w400 ib" :style="{ width: showTips ? '400px' : 'auto' }">
<div @mouseover="showButtonsForLogo = true" @mouseout="showButtonsForLogo = false" class="left ib" v-if="imageUrl" :style="{ background: `url('${ossDomain}${imageUrl}') center center /contain no-repeat` }">
<transition-group name="el-fade-in">
<div :key="1" v-show="showButtonsForLogo || uploading" class="cover"></div>
<roshi-loading :key="4" v-show="uploading && !multiple"></roshi-loading>
<el-button :key="2" size="small" v-show="showButtonsForLogo && showDelete" class="imageButton delete" @click="deleteFile">删除
</el-button>
<el-button :key="3" :style="{ top: showDelete ? '84px' : '62px' }" v-show="showButtonsForLogo" type="success" size="small" class="imageButton again" @click="openUploadingDialog">重新上传</el-button>
</transition-group>
</div>
<div class="left ib" v-show="uploading && multiple">
<div class="cover"></div>
<roshi-loading></roshi-loading>
</div>
<div :id="dropAreaId" :style="{
background: `url('${ossDomain}${ossAssets}upload/20221005/0znbos.png') center 34px /24px 24px no-repeat`,
'border-color': dragIn ? '#0D55CF' : '#e4e9f2',
'border-style': dragIn ? 'dashed' : 'solid'
}" v-show="!imageUrl && !uploading" class="left ib waitUpload">
<p class="leftText">可将本地{{ imgOrVideo }}拖拽到这里</p>
<el-button size="small" type="success" class="imageButton upload" @click="openUploadingDialog">上传</el-button>
</div>
<div class="right ib" v-show="showTips">
<p>格式要求:</p>
<p>1、支持Jpeg、Jpg、Png格式</p>
<p>2、大小不超过5M</p>
</div>
</div>
<input @change="fileChange" type="file" name="file" :multiple=multiple />
</div>
</template>
<script>
export default {
name: "RoshiUpload",
};
</script>
<script setup>
import { ref, reactive, onMounted, onBeforeUnmount, nextTick } from 'vue'
const loadUploadUtils = () => import('@/utils/upload.js');
const props = defineProps({
imageUrl: {
type: String, // 参数类型
default: "", //默认值
required: false, //是否必传
},
showTips: {
type: Boolean,
default: false
},
showDelete: {
type: Boolean,
default: true
},
accept: {
type: String,
default: '.jpg,.jpeg,.png,'
},
limitSize: {
type: Number,
default: 5
},
multiple : {
type:Boolean,
default:true
},
imgOrVideo:{
type:String,
default:'图片'
}
})
const emits = defineEmits(['update:imageUrl', 'change'])
/* reactive data */
const uploadId = ref('fi' + window.app.$get32Id())
const dropAreaId = ref('da' + window.app.$get32Id())
const showButtonsForLogo = ref(true)
const uploading = ref(false)
// 是否放入
const dragIn = ref(false)
/* data */
/* methods */
// 此处定义一个drop容器(省略),并取到该元素;
function dragEnter(e) {
e.stopPropagation();
e.preventDefault();
dragIn.value = true
}
function dragOver(e) {
e.stopPropagation();
e.preventDefault();
}
function dragleave(e) {
e.stopPropagation();
e.preventDefault();
if (e.relatedTarget.id === uploadId.value) {
dragIn.value = false
}
}
function isChildOf(child, parent) {
if (child && parent) {
let parentNode = child.parentNode;
while (parentNode) {
if (parent === parentNode) {
return true;
}
parentNode = parentNode.parentNode;
}
}
return false;
}
function drop(e) {
e.stopPropagation();
e.preventDefault();
if (!e.dataTransfer.files.length) {
return
}
uploading.value = true
dragIn.value = false
// 当文件拖拽到dropBox区域时,可以在该事件取到files
const files = e.dataTransfer.files;
let file = files[0]
let suffix = file.name.substr(file.name.lastIndexOf("."))
if (props.accept.indexOf(suffix) < 0) {
// window.app.$notify({message: '请上传.Jpeg,.Jpg,.Png类型的文件', type:'warning'})
window.app.$tip.warning(`请上传 ${props.accept}类型的文件`)
uploading.value = false
return;
}
if (file.size > 1024 * 1024 * props.limitSize) {
// window.app.$notify({message: '文件大小不能超过5M!', type:'warning'})
window.app.$tip.warning(`文件大小不能超过${props.limitSize}M!`)
uploading.value = false
return
}
upload(file);
}
const openUploadingDialog = () => {
if (uploading.value) {
// window.app.$notify({message: '存在未完成上传的文件,请稍候', type:'warning'})
window.app.$tip.warning('存在未完成上传的文件,请稍候')
return
}
document.querySelector('#' + uploadId.value + ' input').value = "";
document.querySelector('#' + uploadId.value + ' input').click();
}
const deleteFile = () => {
emits('update:imageUrl',)
emits('change')
document.querySelector('#' + uploadId.value + ' input').value = "";
}
const fileChange = (e) => {
uploading.value = true;
let input = e.target;
let files = e.target.files;
if (files && files[0]) {
let file = files[0]
let suffix = file.name.substr(file.name.lastIndexOf("."))
if (props.accept.indexOf(suffix.toLowerCase())< 0) {
// window.app.$notify({message: '请上传.Jpeg,.Jpg,.Png类型的文件', type:'warning'})
window.app.$tip.warning(`请上传${props.accept}类型的文件`)
input.value = ''
uploading.value = false
return false;
}
if (file.size > 1024 * 1024 * props.limitSize) {
// window.app.$notify({message: '文件大小不能超过5M!', type:'warning'})
window.app.$tip.warning(`文件大小不能超过${props.limitSize}M!`)
input.value = ''
uploading.value = false
return false
}
upload(file);
}
}
const upload = (file) => {
loadUploadUtils().then((res) => {
res.uploadFile(file)
.then((res) => {
emits('update:imageUrl', res.url)
emits('change', { ...res, file })
uploading.value = false; console.log(res);
})
.catch((e) => {
console.error(e);
});
});
}
onMounted(() => {
nextTick(() => {
const dropBox = document.querySelector('#' + dropAreaId.value);
dropBox.addEventListener("dragenter", dragEnter, false);
dropBox.addEventListener("dragover", dragOver, false);
dropBox.addEventListener("dragleave", dragleave, false);
dropBox.addEventListener("drop", drop, false);
})
})
onBeforeUnmount(() => {
const dropBox = document.querySelector('#' + dropAreaId.value);
dropBox.removeEventListener("dragenter", dragEnter, false);
dropBox.removeEventListener("dragover", dragOver, false);
dropBox.removeEventListener("dragleave", dragleave, false);
dropBox.removeEventListener("drop", drop, false);
})
defineExpose({
openUploadingDialog
})
</script>
遮罩组件uploading:
<style lang="scss" scoped>
.loadEffect {
// width: 5em;
// height: 5em;
position: relative;
margin: 0 auto;
// scale: 0.3428;
}
.loadEffect span {
display: inline-block;
// width: 0.8em;
// height: 0.8em;
border-radius: 50%;
background: var(--el-color-primary);
position: absolute;
-webkit-animation: load 1.04s ease infinite;
}
@-webkit-keyframes load {
0% {
opacity: 1;
}
100% {
opacity: 0.2;
}
}
.loadEffect span:nth-child(1) {
left: 0;
top: 50%;
// margin-top: -0.4em;
-webkit-animation-delay: 0.13s;
}
.loadEffect span:nth-child(2) {
// left: 0.7em;
// top: 0.7em;
-webkit-animation-delay: 0.26s;
}
.loadEffect span:nth-child(3) {
left: 50%;
top: 0;
// margin-left: -0.4em;
-webkit-animation-delay: 0.39s;
}
.loadEffect span:nth-child(4) {
// top: 0.7em;
// right: 0.7em;
-webkit-animation-delay: 0.52s;
}
.loadEffect span:nth-child(5) {
right: 0;
top: 50%;
// margin-top: -0.4em;
-webkit-animation-delay: 0.65s;
}
.loadEffect span:nth-child(6) {
// right: 0.7em;
// bottom: 0.7em;
-webkit-animation-delay: 0.78s;
}
.loadEffect span:nth-child(7) {
bottom: 0;
left: 50%;
// margin-left: -0.4em;
-webkit-animation-delay: 0.91s;
}
.loadEffect span:nth-child(8) {
// bottom: 0.7em;
// left: 0.7em;
-webkit-animation-delay: 1.04s;
}
</style>
<template>
<div class="roshi-loading">
<div class="loadEffect" :style="{width: 5 * zoom + 'em', height: 5 * zoom + 'em'}">
<span :style="{width: 0.8 * zoom + 'em', height: 0.8 * zoom + 'em','margin-top': -0.4 * zoom + 'em'}"></span>
<span :style="{width: 0.8 * zoom + 'em', height: 0.8 * zoom + 'em', left: 0.7 * zoom + 'em', top: 0.7 * zoom + 'em'}"></span>
<span :style="{width: 0.8 * zoom + 'em', height: 0.8 * zoom + 'em', 'margin-left': -0.4 * zoom + 'em'}"></span>
<span :style="{width: 0.8 * zoom + 'em', height: 0.8 * zoom + 'em', right: 0.7 * zoom + 'em', top: 0.7 * zoom + 'em'}"></span>
<span :style="{width: 0.8 * zoom + 'em', height: 0.8 * zoom + 'em', 'margin-top': -0.4 * zoom + 'em'}"></span>
<span :style="{width: 0.8 * zoom + 'em', height: 0.8 * zoom + 'em', right: 0.7 * zoom + 'em', bottom: 0.7 * zoom + 'em'}"></span>
<span :style="{width: 0.8 * zoom + 'em', height: 0.8 * zoom + 'em', 'margin-left': -0.4 * zoom + 'em'}"></span>
<span :style="{width: 0.8 * zoom + 'em', height: 0.8 * zoom + 'em', left: 0.7 * zoom + 'em', bottom: 0.7 * zoom + 'em'}"></span>
</div>
</div>
</template>
<script>
export default {
name: "RoshiLoading",
props: {
zoom: {
type: Number,
default: 1
}
}
};
</script>
<script setup>
</script>
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
在vue中使用element-ui的el-upload上传单张图片,选中图片之后隐藏上传框可以通过以下步骤实现:
具体的实现代码如下:
<template>
<el-form>
<el-form-item>
<el-upload
class="avatar-uploader"
:show-file-list="false"
:before-upload="beforeAvatarUpload"
:action="uploadUrl"
:on-success="handleAvatarSuccess"
:on-error="handleAvatarError"
:headers="{'Authorization': token}"
:file-list="fileList"
:auto-upload="false"
ref="upload">
<img v-if="imageUrl" :src="imageUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</el-form-item>
</el-form>
</template>
<script>
export default {
data() {
return {
fileList: [],
imageUrl: ''
}
},
methods: {
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg'
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG 格式!')
}
return isJPG
},
handleAvatarSuccess(res, file) {
this.imageUrl = URL.createObjectURL(file.raw)
this.fileList.push(file)
this.$refs.upload.clearFiles() // 上传完毕后清空文件列表,隐藏上传框
},
handleAvatarError() {
this.$message.error('上传头像图片失败!')
}
}
}
</script>
<style scoped>
.avatar-uploader {
display: inline-block;
width: 100px;
height: 100px;
text-align: center;
line-height: 100px;
border-radius: 50%;
border: 1px solid #d9d9d9;
background-color: #f7f7f7;
overflow: hidden;
}
.avatar {
width: 100%;
height: 100%;
display: block;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
cursor: pointer;
transition: color .3s;
}
.avatar-uploader-icon:hover {
color: #409EFF;
}
</style>
以上代码中,el-upload组件的show-file-list属性设置为false,beforeAvatarUpload用来限制上传的图片类型,handleAvatarSuccess处理上传成功的图片,handleAvatarError处理上传失败的情况,imageUrl用来保存上传后的图片地址。同时,我们给 el-upload 绑定了 ref,方便在上传完成后清空文件列表,隐藏上传框。
在 el-form-item 中,我们通过判断是否有 imageUrl 展示图片,如果有则展示图片,否则展示上传图标。由于之前我们已经将上传框隐藏,所以上传图标只会在一开始出现,之后选择图片后就不会再出现了。
如果我的回答解决了您的问题,请采纳!