如何使用 Vue3 和 element

您所在的位置:网站首页 图片上传插件很丑怎么解决 如何使用 Vue3 和 element

如何使用 Vue3 和 element

2024-07-10 06:46| 来源: 网络整理| 查看: 265

原文地址:如何使用 Vue3 和 element-plus 实现图片上传组件 - 之一Yo - 博客园

element-plus 提供了 uploader 组件,但是不好定制化,所以自己又造了个轮子,实现了一个图片上传的组件,它的预期行为是:

还没上传图片时,显示上传卡片上传图片时显示进度条,隐藏上传卡片上传成功时显示图片缩略图,上传失败则显示失败提示支持上传图片的预览和删除

具体如下图所示:

具体代码 图片上传

这里使用的图床是牛图网,无需注册,貌似也没有图片大小的限制,但是请不要上传违规图像。

复制import axios from "axios" import { ElMessage } from 'element-plus' const service = axios.create({ baseURL: "/image" }) service.interceptors.response.use(response => { const code = response.data.code || 200 if (code === 200) { return response.data.data } let msg = response.data.code + " " + response.data.msg ElMessage.error(msg) return Promise.reject('上传图片失败:' + msg) }) /** * 上传图片 * @param {File} file 图片文件 * @param {RefImpl} progress 上传进度 * @returns promise */ function uploadImage(file, progress) { let formData = new FormData(); formData.append("file", file) return service({ url: "/upload", method: "post", data: formData, onUploadProgress(event) { let v = Math.round(event.loaded / event.total * 100) progress.value = v == 100 ? 80 : v }, }) } export { uploadImage }

这里使用 onUploadProgress 来监视上传进度,但是实际上直接使用计算出来的进度往往会和实际的存在很大的偏差,也就是说:即使你还在上传,axios 也会告诉你已经上传完了,所以这里把 100 的进度换成了 80,真正的 100 进度应该在服务器返回 url 时设置。

受到同源策略的限制,我们需要在 vue.config.js 中配置一下代理服务器:

复制module.exports = { devServer: { proxy: { "/image": { target: "https://niupic.com/api", pathRewrite: { "^/image": "" }, }, } } } 上传组件

图片预览功能用的是 vue-easy-light-box,如果没有安装的话可以 npm install --save vue-easy-lightbox@next 安装一下。下面是具体代码:

复制 缩略图 import { ref, computed } from "vue"; import { uploadImage } from "../api/image"; import { Plus } from "@element-plus/icons-vue"; import VueEasyLightbox from "vue-easy-lightbox"; import { ElMessage } from 'element-plus/lib/components'; export default { name: "KilaKilaUploader", emits: ["uploaded", "aboutToUpload", "removed"], components: { Plus, VueEasyLightbox }, setup(props, context) { let progress = ref(0); let isLightBoxVisible = ref(false); let isProgressVisible = ref(false); let isSuccessLabelVisible = ref(false); let imageUrl = ref(""); let localImageUrl = ref(""); let index = ref(0); let isThumbnailVisible = computed(() => localImageUrl.value.length > 0); function openFileDialog() { document.getElementById("file-input").click(); } function onImageAdded() { let fileInput = document.getElementById("file-input"); if (fileInput.files.length == 0) { return; } context.emit("aboutToUpload"); let file = fileInput.files[0]; setImageUrl(URL.createObjectURL(file)); upload(file); } function setImageUrl(url) { let thumbnailEl = document.getElementById("thumbnail"); thumbnailEl.src = localImageUrl.value = url; } function handleThumbnailRemove(file) { imageUrl.value = ""; localImageUrl.value = ""; context.emit("removed", file); } function handleThumbnailPreview() { isLightBoxVisible.value = true; } function handleLightboxHide() { isLightBoxVisible.value = false; } function upload(file) { progress.value = 0; isProgressVisible.value = true; isSuccessLabelVisible.value = false; uploadImage(file, progress).then( (url) => { progress.value = 100; imageUrl.value = url; document.getElementById("thumbnail").src = url; context.emit("uploaded", url); setTimeout(() => { isProgressVisible.value = false; isSuccessLabelVisible.value = true; }, 200); }, () => { isProgressVisible.value = false; localImageUrl.value = ""; context.emit("uploaded", ""); ElMessage.error("哎呀,图片上传出错啦~") } ); } return { progress, imageUrl, localImageUrl, index, isLightBoxVisible, isThumbnailVisible, isProgressVisible, isSuccessLabelVisible, handleThumbnailRemove, handleThumbnailPreview, handleLightboxHide, openFileDialog, onImageAdded, setImageUrl, }; }, }; .uploader { display: flex; } .card { background-color: #fbfdff; border: 1px dashed #c0ccda; border-radius: 6px; width: 148px; height: 148px; overflow: hidden; } .upload-card { display: flex; justify-content: center; align-items: center; transition: all 0.3s; cursor: pointer; &:hover { border-color: #409eff; color: #409eff; } } .thumbnail-card { border: 1px solid #c0ccda; position: relative; #thumbnail { width: 100%; height: 100%; object-fit: contain; display: inline; } .success-label { position: absolute; right: -15px; top: -6px; width: 40px; height: 24px; background: #67c23a; text-align: center; transform: rotate(45deg); box-shadow: 0 0 1pc 1px #0003; .success-icon { position: absolute; left: 13px; top: 1px; transform: rotate(-45deg); } } #progress { width: 100%; height: 100%; position: absolute; top: 0; left: 0; background: rgba(255, 255, 255, 0.7); :deep(.el-progress-circle) { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } } .thumbnail-actions { width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); opacity: 0; transition: all 0.4s ease; display: flex; justify-content: center; align-items: center; position: absolute; top: 0; left: 0; border-radius: 6px; .thumbnail-preview, .thumbnail-delete { cursor: pointer; margin: 0 8px; display: inline-block; } &:hover { opacity: 1; } } } :deep(.vel-img) { box-shadow: 0 5px 20px 2px rgba(0, 0, 0, 0.35); }

在图片上传之前、上传完成和移除图片的时候都会触发相应的自定义事件,父级组件可以处理这些事件来设置图片 url。以上~

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3