【Vue3】使用el-upload封装头像上传组件

预览效果:

默认图片

上传图片后,支持预览和删除

组件使用:

<template>
    <ImageUploader ref="user_ImageUploaderRef" :default-img-url="defaultUserAvatar" size="small"></ImageUploader>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import ImageUploader from '@/components/ImageUploader/index.vue' // 图片上传组件
import defaultUserAvatar from '@/assets/images/Ai-Train/trainPaper/userAvatar.png'

const user_ImageUploaderRef = ref<InstanceType<typeof ImageUploader>>()

// 发起请求 获取用户之前设置的图片
const sendRequest = () => {
    let info = ......
    if(info.avatar){
        user_ImageUploaderRef.value?.setImageUrl(info.avatar)
    }
}

// 发起请求 更新用户现在设置的图片
const submitForm = () => {
    let userAvatarData = user_ImageUploaderRef.value?.getUploadInfo()
    ......
}

</script>

注意:手机端 el-upload 组件不能使用 accept 属性,否则可能会出现点击文件后组件无反应bug

代码实现:

<!-- 图片上传组件 -->
<template>
  <el-upload
    ref="uploadRef"
    class="avatar-uploader"
    action="#"
    :limit="1"
    :disabled="Boolean(uploadImgUrl)"
    accept="image/*"
    :auto-upload="false"
    :show-file-list="false"
    :on-change="handleUploadFile"
  >
    <div class="avatar-img-box" :class="$props.size">
      <template v-if="uploadImgUrl">
        <el-image class="avatar-img" :src="uploadImgUrl" />
        <div class="mask-box" :class="$props.size">
          <el-icon class="mask-icon" @click.stop="previewImage"><ZoomIn /></el-icon>
          <el-icon class="mask-icon" @click.stop="removeImage"><Delete /></el-icon>
        </div>
      </template>
      <template v-else>
        <el-image class="avatar-img" :src="$props.defaultImgUrl" alt="默认图片" />
      </template>
    </div>
  </el-upload>

  <!-- 图片预览弹窗 -->
  <el-image-viewer
    v-if="isPreviewAvatar"
    :url-list="previewUrlList"
    teleported
    hide-on-click-modal
    @close="handleClosePreviewer"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { UploadInstance, UploadRawFile, UploadFile, ElMessage } from 'element-plus'

const $props = defineProps({
  // 默认图片路径
  defaultImgUrl: {
    type: String,
    default: '',
    required: true
  },
  // 组件整体尺寸大小
  size: {
    type: String as () => 'small' | 'default' | 'large',
    default: 'default'
  }
})

const uploadRef = ref<UploadInstance>()
// 用户上传文件
const uploadFile = ref<UploadRawFile>()
// 图片路径
const uploadImgUrl = ref<string>('')

// 上传文件
const handleUploadFile = (file: UploadFile) => {
  if (file.raw && checkUploadFile(file.raw)) {
    uploadFile.value = file.raw
    uploadImgUrl.value = URL.createObjectURL(file.raw)
  } else {
    uploadRef.value?.clearFiles()
    uploadFile.value = undefined
  }
}

// 图片校验
function checkUploadFile(rawFile: UploadRawFile) {
  const isImg = rawFile.type.startsWith('image/')
  const isLt2M = rawFile.size / 1024 / 1024 < 2
  if (!isImg) {
    ElMessage.error('上传文件只能是图片格式!')
  }
  if (!isLt2M) {
    ElMessage.error('文件大小不能超过 2MB!')
  }
  return isImg && isLt2M
}

// 移除图片
const removeImage = () => {
  uploadFile.value = undefined
  uploadImgUrl.value = ''
  uploadRef.value?.clearFiles()
}

const isPreviewAvatar = ref(false)
const previewUrlList = ref<string[]>([])
// 预览图片
const previewImage = () => {
  previewUrlList.value = [uploadImgUrl.value]
  isPreviewAvatar.value = true
}

// 关闭预览组件
const handleClosePreviewer = () => {
  isPreviewAvatar.value = false
  previewUrlList.value = []
}

// 设置预设图片
const setImageUrl = (imgUrl: string) => {
  uploadImgUrl.value = imgUrl
}

// 获取上传的图片数据
const getUploadInfo = () => {
  let result = {
    type: uploadFile.value ? 'file' : 'url',
    data: uploadFile.value || uploadImgUrl.value
  }
  return result
}

defineExpose({
  setImageUrl,
  getUploadInfo
})
</script>

<style scoped lang="scss">
.avatar-uploader {
  .avatar-img-box {
    position: relative;
    padding: 5px;
    border: 1px dotted var(--el-border-color);
    border-radius: 6px;

    &:hover {
      border-color: var(--el-color-primary);
    }

    .avatar-img {
      width: 100%;
      height: 100%;
    }

    &:hover {
      .mask-box {
        display: flex;
      }
    }
  }

  .mask-box {
    position: absolute;
    left: 5px;
    top: 5px;
    align-items: center;
    justify-content: space-evenly;
    opacity: 0.8;
    display: none;
    background-color: #666;
    cursor: auto;

    .mask-icon {
      color: #fff;
      font-size: 16px;
      cursor: pointer;

      &:hover {
        color: var(--el-color-primary);
      }
    }
  }

  .small {
    width: 40px;
    height: 40px;
  }

  .default {
    width: 60px;
    height: 60px;
  }

  .large {
    width: 80px;
    height: 80px;
  }
}
</style>

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: 在Vue使用el-upload组件进行图片上传并预览的方法如下: 首先,在父级组件中引入uploadImg组件,并在el-form-item中使用upload-img组件进行图片上传。\[1\] 然后,在el-upload组件中将auto-upload设置为false,这样不会执行自动上传。同时,给on-change事件绑定一个方法imgSaveToUrl,在该方法中生成可用于本地预览的URL。\[2\] 在imgSaveToUrl方法中,可以通过event.raw获取上传的图片实体,然后根据不同的浏览器生成对应的本地URL。\[3\] 最后,将生成的本地URL赋值给一个变量,用于在页面上展示预览图片。同时,根据需要,可以控制显示和隐藏上传组件和本地预览组件的状态。 这样,就可以实现在Vue使用el-upload组件进行图片上传并预览的功能了。 #### 引用[.reference_title] - *1* [vue3+el-upload上传图片封装组件](https://blog.csdn.net/qq_39536826/article/details/130051704)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Vue中通过el-upload组件实现上传前预览本地图片](https://blog.csdn.net/zrcj0706/article/details/103136634)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值