前言
实现单个的图片上传
使用 Vue3、Element Plus 实现图片的 删除 和 预览
LUpload 组件
- 首先我们在 components 创建一个文件名为 LUpload.vue 的文件
- 代码如下
<template>
<!--
此组件只解决单张图片上传
1、添加图片上传时呈现出 loading 的一个状态
2、添加在图片上传完成后,鼠标放在图片上呈现出 “图片预览”、“删除图片” 的效果
3、自定义图片大小以及方形圆形图片
-->
<div class="l-upload" :class="round ? 'round' : ''">
<!-- el-upload 组件 -->
<el-upload class="avatar-uploader" :style="uploadStyle" :headers="headers" :action="action" :show-file-list="false"
:on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload" :on-progress="handleAvatarProgress"
v-loading="uploadLoading">
<div class="avatar" v-if="modelValue" @click.stop>
<el-image class="image" :src="modelValue" ref="imageRef" />
<!-- 鼠标 hover 是图片上方遮罩层 -->
<div class="el-upload-actions">
<!-- 图片预览ICON -->
<div class="item" @click="handlePictureCardPreview">
<el-icon size="18" color="#fff">
<ZoomIn />
</el-icon>
</div>
<!-- 图片删除ICON -->
<div class="item" @click="handleRemove">
<el-icon size="18" color="#fff">
<Delete />
</el-icon>
</div>
</div>
</div>
<el-icon v-else class="avatar-uploader-icon">
<Plus />
</el-icon>
</el-upload>
<!-- 实现图片大图预览 -->
<!-- 注意 ElImageViewer 组件必须要使用v-if判断 -->
<ElImageViewer v-if="isImageView" :url-list="srcList" @close="imageClose"></ElImageViewer>
</div>
</template>
<script setup lang="ts">
import { defineProps, reactive, ref, toRefs, defineEmits } from 'vue'
import { Plus, ZoomIn, Delete } from '@element-plus/icons-vue' // 引入 Element 中的图标
import { ElImageViewer } from 'element-plus'; // 实现图片预览的组件,注意这是 element-plus 中的哦
import { getDomainName } from "@/utils/index"; // 获取 域名地址
import Cookies from 'js-cookie'
const props = defineProps({
// 父组件 v-model 绑定的值
modelValue: {
type: String
},
// 图片上传时的地址
action: {
type: String,
default: 'http://127.0.0.1:1024/image/upload'
},
// 定义 el-upload 组件的样式
uploadStyle: {
type: Object,
default: {
width: "200px",
height: "200px",
}
},
// 图片是否为圆形
round: {
type: Boolean,
default: false
}
})
const state = reactive({
uploadLoading: false, // 图片文件大时 呈现出一个上传中的loading状态
headers: { // el-upload 自定义 headers 头(根据自己的接口看是否需要)
Authorization: Cookies.get('Token'),
ContentType: 'application/json;charset=utf-8'
},
isImageView: false, // 图片预览时的状态
srcList: [] as any // 图片预览列表(可以是多张)
})
const { headers, uploadLoading, isImageView, srcList } = toRefs(state)
const imageRef = ref()
const emit = defineEmits(['update:modelValue'])
// 预览图片
function handlePictureCardPreview() {
state.isImageView = true
}
// 关闭图片预览
function imageClose() {
state.isImageView = false
state.srcList = [] // 每次关闭图片预览时清空一下
}
// 删除图片
function handleRemove() {
emit('update:modelValue', "")
}
// 图片上传成功
function handleAvatarSuccess(response: any, file: any, fileList: any) {
// response 上传成功返回的数据,根据自己的情况来写。
let url = getDomainName() + response.data.url
emit('update:modelValue', url)
state.srcList.push(url)
state.uploadLoading = false
}
// 图片上传之前
function beforeAvatarUpload() {
}
// 图片上传时
function handleAvatarProgress() {
state.uploadLoading = true
}
</script>
<style scoped lang="scss">
.l-upload {
::v-deep .el-upload {
width: 100%;
height: 100%;
border: 1px dashed #dcdfe6;
}
.avatar-uploader {
.avatar {
width: 100%;
height: 100%;
cursor: auto;
position: relative;
.image {
width: 100%;
height: 100%;
}
.el-upload-actions {
top: 0;
left: 0;
cursor: auto;
width: 100%;
height: 100%;
transition: 0.5s;
position: absolute;
background: rgba($color: #000000, $alpha: 0.5);
opacity: 0;
display: flex;
align-items: center;
justify-content: center;
.item {
width: 30px;
height: 30px;
display: flex;
cursor: pointer;
align-items: center;
justify-content: center;
}
}
&:hover {
.el-upload-actions {
opacity: 1;
display: flex;
align-items: center;
justify-content: center;
}
}
}
}
}
.round {
::v-deep .el-upload {
border-radius: 50px;
overflow: hidden;
}
}
</style>
父组件,LUpload.vue的使用
- 首先我们肯定需要先引入一下 LUpload.vue 组件了
<template>
<div class="dashboard">
<!-- LUpload组件 -->
<LUpload v-model="url"></LUpload>
</div>
</template>
<script setup lang="ts">
import { reactive, toRefs, ref, onMounted } from 'vue'
// 引入 LUpload 组件,不要照抄哦,看好自己的路径(如何组册为全局组件这里就不过多说了)
import LUpload from "@/components/LUpload/index.vue"
const state = reactive({
url: ""
})
const { url } = toRefs(state)
onMounted(() => {
})
</script>
<style scoped lang="scss">
.bg {
width: 100px;
height: 100px;
}
</style>
接下来我们看一下效果吧
有点模糊,就这样看吧。