返回顶部
首页 > 资讯 > 前端开发 > JavaScript >ElementUI修改实现更好用图片上传预览组件
  • 612
分享到

ElementUI修改实现更好用图片上传预览组件

2024-04-02 19:04:59 612人浏览 独家记忆
摘要

目录前言1. 功能设计2. 实现2.1 图片预览 PicturePreviewer2.2 图片上传 ImageUpload3. 后记前言 嗯,,,跟之前封装“全局 Loa

前言

嗯,,,跟之前封装“全局 Loading”的出发点基本一样,因为产品觉得 ElementUI 提供的默认上传组件,使用“照片墙”或者“缩略图”模式都需要去改动原本的组件样式,并且缩略图尺寸也不能调整,预览模式也会对原始图片进行缩放和处理,不符合系统本身的样式规范。

最离谱的是,预览模式居然有背景色,但是背景色又没有填满整个 model 的背景区域,,,甚至还出现了滚动条!!!

所以,为了更好的配合产品和UI,特地重新编写了一个图片上传组件。

1. 功能设计

嗯,既然是图片上传,那么肯定只支持图片文件了。因为是内部项目,所以也保留了 Http 上传部分,大家可以参照 ElementUI 适当修改。

修改后的上传组件支持以下功能:

  • 上传(基础中的基础)
  • 实现 v-model 语法糖绑定上传数据列表(嗯,,,也很基础)
  • 需要支持大图预览
  • 不能换行,超出宽度显示滚动条且支持鼠标控制(不用 shift 的那种)

功能设计完成之后,大致的页面样式就是这样的:

2. 实现

为了能够适应更多的场景,我决定把预览部分也直接提取出来。

2.1 图片预览 PicturePreviewer

这里的图片预览是基于 ElDialog 开发的,支持翻页、循环等。

本身不依赖外部的图片元素,可以和 ElDialog 一样直接使用 visible 属性来控制显示和隐藏。

 <template>
   <el-dialog
     :title="title"
     :visible="visible"
     :close-on-click-modal="false"
     width="1000px"
     destroy-on-close
     append-to-body
     @close="closeDialog"
   >
     <div class="q-picture__img-box">
       <div
         class="q-picture__prev-btn"
         @mouseover="leftBtnStatus = true"
         @mouseleave="leftBtnStatus = false"
       >
         <transition name="btn-fade">
           <el-button
             v-show="leftBtnStatus && isNeeding"
             circle
             icon="el-icon-arrow-left"
             @click="lastImage()"
           />
         </transition>
       </div>
       <img v-show="visible" :src="currentSrc" alt="" v-loading="loading" @load="loading = false" />
       <div
         class="q-picture__next-btn"
         @mouseover="rightBtnStatus = true"
         @mouseleave="rightBtnStatus = false"
       >
         <transition name="btn-fade">
           <el-button
             v-show="rightBtnStatus && isNeeding"
             circle
             icon="el-icon-arrow-right"
             @click="nextImage()"
           />
         </transition>
       </div>
     </div>
   </el-dialog>
 </template>
 <script>
 export default {
   name: "PicturePreviewer",
   props: {
     visible: { type: Boolean, default: false },
     pageable: { type: Boolean, default: true },
     recyclable: { type: Boolean, default: true },
     src: { type: [String, Array], required: true },
     title: { type: String, default: "图片预览" },
     current: { type: Number, default: 0 }
   },
   data() {
     return {
       currenTKEy: -1,
       leftBtnStatus: false,
       rightBtnStatus: false,
       loading: false
     };
   },
   computed: {
     isNeeding: function () {
       return typeof this.src === "object" && this.pageable && this.src && this.src.length > 1;
     },
     currentSrc: function () {
       if (typeof this.src === "string") return this.src;
       if (this.src && this.src.length) {
         return this.src[this.currentKey] || "";
       }
       return "";
     }
   },
   methods: {
     closeDialog() {
       this.$emit("update:visible", false);
     },
     lastImage() {
       if (this.currentKey - 1 === -1) {
         if (this.recyclable) this.currentKey = this.src.length - 1;
         else this.$message.info("当前已经是第一张图片");
       } else {
         this.currentKey = this.currentKey - 1;
       }
     },
     nextImage() {
       if (this.currentKey + 1 === this.src.length) {
         if (this.recyclable) this.currentKey = 0;
         else this.$message.info("当前已经是最后一张图片");
       } else {
         this.currentKey = this.currentKey + 1;
       }
     }
   },
   watch: {
     current: {
       handler: function (val) {
         if (val) this.currentKey = val;
         else this.currentKey = 0;
       },
       immediate: true
     }
   }
 };
 </script>

2.2 图片上传 ImageUpload

图片预览处理完成够,就可以处理图片上传了。

 <template>
   <div
     class="q-upload__preview"
     ref="pictures"
     :title="messageInfo"
     @mouseenter="horizontalRolling"
   >
     <slot name="preSlot"></slot>
     <input
       class="q-upload__file-input"
       type="file"
       ref="fileInput"
       name="fileInput"
       @change="fileChange"
       :accept="accept"
     />
     <div
       class="q-upload__file-label"
       v-loading="fileLoading"
       @click="selectFile"
       v-show="fileLists.length < limitNum && !disabled"
     >
       <i class="el-icon-plus"></i>
     </div>
     <slot name="middle"></slot>
     <div class="q-upload__pre-img" v-for="(i, k) in fileLists" :key="i.smallUrl">
       <img class="q-upload__img" :src="i.smallUrl ? i.smallUrl : i.url" />
       <div class="q-upload__mask">
         <i v-if="prev" class="el-icon-zoom-in" @click="imgPreview(i, k)"></i>
         <i class="el-icon-delete" v-if="!disabled" @click="imgRemove(k)"></i>
       </div>
     </div>
     <slot name="endSlot"></slot>
     <picture-previewer
       :visible.sync="dialogImageVisible"
       :src="imageUrls"
       :current="currentImage"
     />
   </div>
 </template>
 <script>
 import Utils from "../../src/utils/commonUtils";
 export default {
   name: "ImageUpload",
   props: {
     active: { type: String, default: "/api/file/upload" },
     accept: { type: String, default: "" },
     limitNum: { type: Number, default: 9 },
     size: { type: Number, default: 10 },
     prev: { type: Boolean, default: true },
     disabled: { type: Boolean, default: false },
     value: { type: Array, default: () => [] }
   },
   data() {
     return {
       fileLoading: false,
       dialogImageVisible: false,
       dialogImageUrl: "",
       currentImage: 0,
       fileLists: [],
       messageInfo: ""
     };
   },
   computed: {
     imageUrls: function () {
       return this.fileLists.map(o => o.url);
     }
   },
   methods: {
     async validateImage(file) {
       const isJPEG = file.type === "image/jpeg";
       const isJPG = file.type === "image/jpg";
       const isPNG = file.type === "image/png";
       const isBMP = file.type === "image/bmp";
       const isLtSize = file.size / 1024 / 1024 < this.size;
       if (!(isJPEG || isJPG || isPNG || isBMP)) {
         return {
           status: false,
           message: `上传图片必须是${this.accept}格式!`
         };
       }
       if (!isLtSize) {
         return {
           status: false,
           message: "上传图片大小不能超过 " + this.size + " MB!"
         };
       }
       return { status: true, message: "" };
     },
     // 选择文件
     selectFile() {
       this.$refs.fileInput.value = null; // 置空,防止删除后无法再次选择
       this.$refs.fileInput.click();
       return true;
     },
     // 文件选取之后·
     async fileChange(el) {
       const file = [...el.target.files][0];
       let { status, message } = await this.validateImage(file);
       if (status) {
         this.fileLoading = true;
         await this.customHttpRequest(file);
       } else {
         this.$message.error(message);
         return false;
       }
     },
     // 上传
     async customHttpRequest(file) {
       try {
         let fData = Utils.createUploadFORM(file);
         let {
           data: { data, status, message }
         } = await this.$http.post(this.active, fData.formData, fData.config);
         if (status) {
           this.fileLists.unshift(data);
           this.$emit("success", data);
         } else {
           this.$message.error(message);
           this.$emit("error");
         }
       } finally {
         this.fileLoading = false;
       }
     },
     imgPreview(file, k) {
       this.dialogImageUrl = file.url;
       this.dialogImageVisible = true;
       this.currentImage = k;
     },
     imgRemove(index) {
       this.fileLists.splice(index, 1);
       this.$emit("input", this.fileLists);
       this.$emit("change", this.fileLists);
       this.$emit("blur", this.fileLists);
     },
     horizontalRolling() {
       if (this.$refs["pictures"].clientWidth < this.$refs["pictures"].scrollWidth) {
         this.messageInfo = "滚动滚轮查看所有信息";
       } else {
         this.messageInfo = "";
       }
       this.$refs["pictures"].addEventListener("mousewheel", this.$_scrollEvent);
       this.$once("hook:beforeDestroy", () => {
         this.$refs["pictures"].removeEventListener("mousewheel", this.$_scrollEvent);
       });
     },
     $_scrollEvent(e) {
       let left = this.$refs["pictures"].scrollLeft;
       this.$refs["pictures"].scrollLeft = e.deltaY > 0 ? left + 40 : left - 40;
     }
   },
   watch: {
     value: {
       deep: true,
       immediate: true,
       handler: function () {
         this.fileLists = typeof this.value === "string" ? JSON.parse(this.value) : this.value;
         if (!this.fileLists) this.fileLists = [];
       }
     },
     fileLists: {
       deep: true,
       immediate: false,
       handler: function () {
         if (this.value && this.value.length > this.limitNum) {
           this.$message.warning(`最多可以上传【 ${this.limitNum} 】张图片!!`);
         }
         this.$emit("input", this.fileLists);
         this.$emit("change", this.fileLists);
       }
     }
   }
 };
 </script>

因为是内部项目,所以上传方法还是使用的实例上的 axiOS 方法来发送上传请求的;在独立组件库中依然应该通过 props 的方式传递项目中定义的 http 请求方法。

组件接收一个最大张数限制 limitNum 和文件大小限制 size,以及预览控制 prev 和禁用状态 disabled

在选择文件之后会立即上传、点击已上传文件则是预览当前文件;当前内部也依赖了 ElementUI 的 Message 组件,用来显示提示信息。

在预览区域前后也增加了一个插槽,用来插入开发者需要的其他信息。

在整个组件的 Dom 节点上,会添加一个鼠标的 mouseenter 事件,当鼠标在组件内部的时候,则计算内部的缩略图区域与外层节点的大小进行比较,如果大于外层父节点的宽度的话,则提示用户通过鼠标滚轮来控制缩略图区域的滚动。

3. 后记

整个组件虽然可以满足当时的系统的一个需求,但是仔细研究代码的话会发现依然有很多细节的地方需要修复。例如:

  • 组件的 mouseenter 事件,每次被触发时都会给 dom 添加一个鼠标监听事件,而没有在鼠标移出时及时销毁监听
  • 没有增加自定义 http 配置
  • 没有控制预览组件的配置项
  • 缩略图区域没有尺寸控制

等等一系列的问题,所以我们在抽离组件、公共逻辑的时候,还是需要尽可能的保留以后扩展的可能性,减少与外界逻辑或者业务的关联。

以上就是ElementUI修改实现更好用图片上传预览组件的详细内容,更多关于ElementUI图片上传预览的资料请关注编程网其它相关文章!

--结束END--

本文标题: ElementUI修改实现更好用图片上传预览组件

本文链接: https://lsjlt.com/news/168736.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • ElementUI修改实现更好用图片上传预览组件
    目录前言1. 功能设计2. 实现2.1 图片预览 PicturePreviewer2.2 图片上传 ImageUpload3. 后记前言 嗯,,,跟之前封装“全局 Loa...
    99+
    2024-04-02
  • Vant实现上传多个图片或视频,更改视频预览图
    目录Vant上传多个图片或视频,更改视频预览图需求最终成果过程Vant上传压缩图片;多图片压缩上传Vant上传多个图片或视频,更改视频预览图 需求 vant上传多个视频或图片图片和视...
    99+
    2022-11-13
    Vant上传多个图片 Vant上传多个视频 Vant更改视频预览图
  • vue.js如何实现图片上传预览及图片更换功能
    这篇文章将为大家详细讲解有关vue.js如何实现图片上传预览及图片更换功能,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。效果图:样式以及效果图一并展示1.HTML<...
    99+
    2024-04-02
  • html5怎么实现图片上传预览
    这篇文章主要介绍“html5怎么实现图片上传预览”,在日常操作中,相信很多人在html5怎么实现图片上传预览问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”html5怎么实现图...
    99+
    2024-04-02
  • AngularJs如何实现上传前预览图片
    小编给大家分享一下AngularJs如何实现上传前预览图片,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!demo.html:&l...
    99+
    2024-04-02
  • javascript如何实现图片预览和上传
    小编给大家分享一下javascript如何实现图片预览和上传,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!具体内容如下var dailiApply = { ...
    99+
    2024-04-02
  • Vue+SSM实现图片上传预览效果
    现在的需求是:有一个上传文件按钮,当我们点击按钮时,可以选择需要上传的文件,确定后图片显示在界面上。 说明:本项目前端使用的Vue,后台用的SSM搭建的,服务器是Tomcat,数据库...
    99+
    2024-04-02
  • vue.js如何实现图片转Base64上传图片并预览
    这篇文章主要为大家展示了“vue.js如何实现图片转Base64上传图片并预览”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“vue.js如何实现图片转Base6...
    99+
    2024-04-02
  • thinkphp5加layui实现图片上传功能(带图片预览)
    目录1、引入文件2、HTML部分3、功能实现4、后台处理图片上传保存内容网站中很多表单都会用到上传图片,logo,照片,用户也会上传图片,这个时候网站就需要一个上传图片的功能,而且在...
    99+
    2023-03-11
    thinkphp5加layui实现图片上传功能 layui图片上传 thinkphp5图片上传
  • JS+HTML5如何实现上传图片预览效果
    这篇文章给大家分享的是有关JS+HTML5如何实现上传图片预览效果的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。示例代码如下:<!DOCTYPE HTML>...
    99+
    2024-04-02
  • html5中怎么实现图片上传预览功能
    今天就跟大家聊聊有关html5中怎么实现图片上传预览功能,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。<!DOCTYPE html&...
    99+
    2024-04-02
  • jquery如何实现图片上传前本地预览
    这篇文章主要为大家展示了“jquery如何实现图片上传前本地预览”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“jquery如何实现图片上传前本地预览”这篇文章吧...
    99+
    2024-04-02
  • JQ图片文件上传之如何实现前预览功能
    小编给大家分享一下JQ图片文件上传之如何实现前预览功能,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!1、先准备一个divonchange触发事件<input type=&q...
    99+
    2024-04-02
  • JS如何实现上传图片实时预览功能
    这篇文章主要为大家展示了“JS如何实现上传图片实时预览功能”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“JS如何实现上传图片实时预览功能”这篇文章吧。前段时间在...
    99+
    2024-04-02
  • 如何实现Ajax上传图片及上传前先预览功能
    这篇文章将为大家详细讲解有关如何实现Ajax上传图片及上传前先预览功能,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。上传之前的预览方式一先来说说图片上传之前的预览问题。这...
    99+
    2024-04-02
  • javascript实现上传图片并预览的效果实现代码
    今天用alphaimageloader滤镜的src属就是其中的主角它将使用绝对或相对url地址指定背景图像。假如忽略此参数,滤镜将不会作用。复制代码 代码如下: <!docty...
    99+
    2022-11-21
    上传图片 预览
  • Vue+UpLoad实现上传预览和删除图片的实践
    1、用vue+Element完成一个图片上传、点图预览、加删除功能,如图: 2.首先我们再组件中引入这一段代码,每个属性的使用也都放在这里了: <el-upload cl...
    99+
    2024-04-02
  • vue使用element实现上传图片和修改图片功能
    目录前言一、应用场景1.上传图片并进行放大预览2.图片上传代码二、修改已经上传的图片,并展示到图片列表中1.效果展示(先展示原来的图片,再上传新图片,也可删除原来的图片)2.编辑代码...
    99+
    2024-04-02
  • vue如何实现上传图片组件
    这篇文章给大家分享的是有关vue如何实现上传图片组件的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。未上传状态上传状态其他状态(查看/删除)自定义组件文件名称 - 这里叫UploadImg.vue<templ...
    99+
    2023-06-25
  • angularjs怎么实现多张图片上传并预览功能
    这篇文章主要介绍angularjs怎么实现多张图片上传并预览功能,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!具体内容如下directive.js    angu...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作