vue3 element-plus demo 前端本地化处理图片预览

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值