<template>
<div class="upLoadBox">
<div class="upLoadStyle">
<!-- 上传组件:Element Plus 版 el-upload -->
<el-upload
class="upload-demo"
action="#"
:limit="value !== 'only' ? (value === 'post' ? 5 : 10) : 1"
multiple
drag
list-type="picture"
v-model:file-list="fileList"
@change="handleFileSelect"
@remove="handleFileRemove"
:auto-upload="false"
accept="image/*"
>
<!-- Element Plus 图标:需单独引入 -->
<Upload class="el-icon-upload" />
<div class="el-upload__text">
将选中文件拖到此处,或<em>点击上传</em>
</div>
<div slot="tip" class="el-upload__tip">支持JPG、PNG、GIF等图片格式</div>
</el-upload>
<!-- 清空按钮 -->
<el-button
v-if="value !== 'only'"
class="UpLoadButton"
type="danger"
@click="clearAll"
style="margin-top: 10px"
>
清空
</el-button>
</div>
<!-- 前端预览图片列表 -->
<div
v-if="previewUrls.length > 0"
class="resultBox"
style="margin-top: 20px"
>
<div v-for="(url, index) in previewUrls" :key="index" class="resultItem">
<el-card :body-style="{ padding: '10px' }">
<!-- 图片预览(支持点击放大) -->
<el-image
style="width: 120px; height: 120px; object-fit: cover"
:src="url"
:preview-src-list="[url]"
/>
<!-- 临时URL显示(可选) -->
<div style="margin-top: 10px; font-size: 12px; color: #666">
临时预览地址:{{ url }}
</div>
</el-card>
</div>
</div>
</div>
</template>
<script setup>
// 1. 引入依赖(Element Plus 组件 + 图标)
import { ElUpload, ElButton, ElCard, ElImage, ElMessage } from "element-plus";
import { Upload } from "@element-plus/icons-vue"; // 上传图标
import { ref, onBeforeUnmount } from "vue"; // Vue 3 核心API
// import CutImg from '@/components/cutImg.vue' // 裁剪组件(如需保留,需同步适配Vue3)
// 2. 接收Props(Vue 3 用 defineProps 定义)
// const props = defineProps({
// value: {
// type: String,
// default: ''
// },
// isNeedCut: {
// type: Boolean,
// default: false
// },
// isRichText: {
// type: Boolean,
// default: false
// },
// isNeedCopyUrl: {
// type: Boolean,
// default: false
// }
// })
// 3. 定义响应式数据(ref 替代 Vue 2 的 data)
const fileList = ref([]); // 上传文件列表(Element Plus 双向绑定)
const previewUrls = ref([]); // 本地预览URL数组
// 4. 核心方法:选择文件后生成临时预览URL
const handleFileSelect = (uploadFile) => {
const file = uploadFile.raw; // 获取本地File对象
// 校验是否为图片
if (!file.type.startsWith("image/")) {
ElMessage.error("请选择图片文件(JPG/PNG/GIF等)");
return;
}
// 生成浏览器临时URL(核心:前端本地预览)
const tempUrl = URL.createObjectURL(file);
previewUrls.value.push(tempUrl); // 响应式更新预览列表
};
// 5. 方法:删除文件并释放临时URL
const handleFileRemove = (uploadFile, newFileList) => {
fileList.value = newFileList; // 更新文件列表
// 找到对应临时URL并移除
const targetIndex = previewUrls.value.findIndex(
(url) => url.includes(uploadFile.uid) // 用文件唯一ID匹配
);
if (targetIndex > -1) {
// 释放临时URL(避免内存泄漏)
URL.revokeObjectURL(uploadFile.raw);
previewUrls.value.splice(targetIndex, 1); // 删除预览URL
}
};
// 6. 方法:清空所有文件和预览
const clearAll = () => {
// 释放所有临时URL
previewUrls.value.forEach((url, index) => {
const file = fileList.value[index];
if (file) URL.revokeObjectURL(file.raw);
});
// 重置响应式数据
fileList.value = [];
previewUrls.value = [];
};
// 7. 生命周期:组件销毁前释放所有临时URL(Vue 3 用 onBeforeUnmount)
onBeforeUnmount(() => {
previewUrls.value.forEach((url, index) => {
const file = fileList.value[index];
if (file) URL.revokeObjectURL(file.raw);
});
});
// 8. 暴露组件(如需外部使用CutImg,需定义)
// defineExpose({
// clearAll, // 暴露清空方法(可选)
// CutImg
// })
</script>
<style lang="scss" scoped>
.upLoadBox {
padding: 20px;
}
.upLoadStyle {
width: max-content;
.UpLoadButton {
width: 100%;
}
}
.resultBox {
display: flex;
gap: 15px;
flex-wrap: wrap; // 自动换行
}
.resultItem {
width: 120px;
}
/* 适配Element Plus样式(如需微调) */
::v-deep(.el-upload-list__item) {
margin-bottom: 10px;
}
</style>
vue3 element-plus demo 前端本地化处理图片预览
最新推荐文章于 2025-10-14 15:53:37 发布