Element-ui上传图片按顺序展示
背景
不知道你上传图片的时候有没有过这样的情况,批量上传多张图片,可能因为图片大小或者网络问题,导致图片返回的顺序和上传时的顺序不一样。因为我们公司是做电商的,即使我们的支持拖动排序,运营还是希望图片能够严格的按照他们上传的顺序展示。
解决问题
在上传组件的on-success的方法中,有3个参数 response, file, fileList 其中fileList就是之前上传成功图片的集合,且upload组件提供了clearFiles方法,用来清空fileList,每次上传成功,我们调用clearFiles方法就行了
上代码
<template>
<!-- 上传单张图片 -->
<div v-if="!multiple" class="image-item">
<div class="image-wrap" v-if="imgUrl">
<img :src="imgUrl" :style="imgStyle" />
<div class="icon-wrap" @click.stop="removeFile">
<i class="el-icon-delete"></i>
</div>
</div>
<el-upload
v-else
ref="imageUpload"
action="//up.qbox.me"
:before-upload="beforeUpload"
:on-success="handleSuccess"
class="image-uploader"
:on-error="onError"
:data="form"
:show-file-list="false"
:disabled="loading"
accept="image/*">
<i :class="loading ? 'el-icon-loading' : 'el-icon-plus'" :style="imgStyle"></i>
</el-upload>
</div>
<!-- 上传多张图片 -->
<div class="image-list" v-else>
<draggable v-model="showImgList" :options="{group:'image'}" @change="dragChange">
<div v-for="(image, index) in showImgList" :key="index" class="image-wrap">
<img :src="imgUrl" :style="imgStyle" />
<div class="icon-wrap" @click.stop="removeFile(index)">
<i class="el-icon-delete"></i>
</div>
</div>
<el-upload
ref="imageListUpload"
action="//up.qbox.me"
:before-upload="beforeUpload"
:on-success="handleSuccess"
class="image-uploader"
:on-error="onError"
:data="form"
multiple
:disabled="loading"
:show-file-list="false"
accept="image/*">
<i :class="loading ? 'el-icon-loading' : 'el-icon-plus'" :style="imgStyle"></i>
</el-upload>
</draggable>
</div>
</template>
<script type="text/babel">
/**
* 上传图片或文件
*/
import md5 from 'blueimp-md5'
import draggable from 'vuedraggable' export default {
props: {
// 接收和返回的数据
data: {
type: [Array, String, Object],
default: () => {
return ''
}
},
// 上传多个文件时,文件限制的个数
limit: {
type: Number,
default: () => {
return 100
}
},
// 一次上传多个
multiple: {
type: Boolean,
default: false,
},
//图片展示的宽度
imgWidth: {
type: Number,
default: 150,
},
imgHeight: {
type: Number,
default: 150,
},
//期望上传图片的宽度
rule: [ Object, Function ]
},
data() {
return {
imgUrl: '',
imageCdn: '', //图片的cdn
form: {
token: '', //七牛上传的token
},
showImgList: [],
fileList: [],
clipboard: false,
isDrag: false,
handleSuccess: null,
loading: false,
}
},
components: { draggable },
watch: {
data: {
handler(value) {
if (!this.multiple) {
this.imgUrl = value
} else if (this.multiple) {
this.showImgList = value
}
},
immediate: true
}
},
computed: {
imgStyle() {
return {
width: this.imgWidth + 'px',
height: this.imgHeight + 'px',
lineHeight: this.imgHeight + 'px',
}
}
},
mounted() {
//防抖
this.handleSuccess = _.debounce(this.uploadSuccess, 500)
},
methods: {
beforeUpload(file) {
if (file.type.split('/')[0] === 'image') {
let tempSize = file.size / 5242880
if (tempSize > 1) {
this.$message.error('图片尺寸不得大于5M!')
return false
}
}
this.loading = true
let tempNames = file.name.split('.')
let fileType = tempNames[tempNames.length - 1]
let curr = (+new Date()).toString()
let random = Math.random() * 10000
let md5Str = md5(`${curr}${random}${file.name}`)
this.form.key = `ai-admin/${md5Str}.${fileType}`
},
async uploadSuccess(response, file, fileList) {
try {
for (let fileInfo of fileList) {
let imageInfo = await this.getImageInfo(fileInfo.response.key)
if (this.rule) {
this.rule(imageInfo, (error) => {
if (error) {
throw(error)
}
})
}
if (imageInfo.width > 2048 || imageInfo.height > 2048) {
throw(new Error('图片长或者宽不能超过2048'))
} else {
if (this.type === 'image') {
this.imgUrl = response.key
this.$emit('update:data', response.key)
} else {
if (this.showImgList.length >= this.limit) { // 限制图片张数
this.showImgList.length = this.limit
throw(new Error(`最多上传 ${this.limit} 张图片`))
}
this.showImgList.push(imageInfo)
this.$emit('update:data', this.showImgList)
}
}
}
} catch (error) {
this.$message.error(error.message)
} finally {
this.loading = false
this.$refs.imageListUpload && this.$refs.imageListUpload.clearFiles()
this.$refs.imageUpload && this.$refs.imageUpload.clearFiles()
}
},
removeFile(index) {
this.$confirm('确定删除该图片吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
if (this.type === 'image') {
this.$emit('update:data', typeof this.data === 'object' ? {} : '')
} else {
this.showImgList.splice(index, 1)
this.$emit('update:data', this.showImgList)
}
})
},
onError() {
this.$message.error('上传文件失败')
},
getImageInfo(url){
return new Promise((resolve, reject)=>{
let image = new Image()
image.src = `${this.imageCdn}${url}`
image.onload = () => {
resolve({
image: url,
width: image.width,
height: image.height
})
}
image.onerror = () => {
reject(new Error('Could not load image at ' + url));
};
})
},
dragChange() {
this.$emit('update:data', this.showImgList)
},
handleRemove(file, fileList) {
let imgList = fileList.map(item => {
return item.response.key
})
this.$emit('update:data', imgList)
},
handlerClipboard(event) {
if (this.clipboard) {
const rawFile = getImageFromClipboard(event)
if (rawFile) {
this.$refs.elUpload.handleStart(rawFile)
this.$refs.elUpload.$refs['upload-inner'].upload(rawFile)
}
}
},
}
}
</script>
<style lang="less" scoped>
.image-list, .image-item {
display: flex;
.image-wrap {
position: relative;
display: inline-block;
box-sizing: content-box;
margin: 0 8px 8px 0;
vertical-align: top;
&:hover {
.icon-wrap {
opacity: 1;
}
}
.icon-wrap {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 30px;
cursor: default;
text-align: center;
color: #fff;
opacity: 0;
font-size: 20px;
background-color: rgba(0, 0, 0, .7);
transition: opacity .3s;
.el-icon-zoom-in {
cursor: pointer;
margin-right: 8px;
}
.el-icon-delete {
cursor: pointer;
}
}
}
}
.image-item {
display: inline-flex;
}
/deep/.image-uploader {
display: inline-block;
.el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
[class^="el-icon"] {
font-size: 28px;
color: #8c939d;
text-align: center;
}
&:hover {
border-color: #409EFF;
}
}
}
</style>
注意
这是我封装的上传图片的组件,支持 类v-model的传参方式,上传多张图时支持拖动,写图片规则(例如宽高是多少),删除图片
特别注意:因为我们还封装了图片组件,在这里被我替换了,所以图片展示有上面的代码可能有点问题,稍微改下就行
用法(只允许上传正方形的图)
<template>
<image-upload :data.sync="image" :rule="rule"></image-upload>
</template>
<script>
export default {
data(){
let validate = ({ width, height }, callback) => {
if (width === height) {
callback()
} else {
callback(new Error('请上传正方形的图'))
}
}
return {
rule: validate,
image: ''
}
},
}
</script>
效果

Element-ui上传图片按顺序展示的更多相关文章
- element ui表格表头顺序错乱的问题
因为在项目中两个表格共用了同一个组件, 但由于表头不完全相同, 就通过v-if来控制表头的显示隐藏,没想到造成了表头顺序的错乱, 经过多方查找资料,最后找到了解决方法: 即为每一列el-table-c ...
- element ui 上传图片
upload在form模块,在demo的基础上包个form然后action写地址用?&拼接参数即可
- vue项目中使用element ui上传图片到七牛
1.获取token值 后台有接口调用直接返回token值 //请求后台拿七牛云token async getQiniuToken() { //token let uploadtoken = await ...
- 上传图片组件封装 element ui
// element ui 文档地址: http://element.eleme.io/#/zh-CN <template> <div> <div class=" ...
- vue问题三:element ui的upload组件上传图片成功和移除事件
element ui的upload组件上传图片成功和移除事件: 登录后获取到后台传的token存到中: sessionStorage.setItem("token",data.ob ...
- Element UI 中组件this.$message报错
最近在做毕设的时候,用Element UI中的消息提示message一直报以下的错误: 展示的效果也不好看,没有图标什么的: 但我明明有在main.js引入了element-ui 呀,因为毕设时间很赶 ...
- Element ui tree结合Vue使用遇到的一些问题(一)
下图是一个后台管理系统,展示的是角色列表 当我点击编辑的时候,弹出一个模态框,如下图 功能需求:点击编辑按钮,弹出模态框,选择权限那块,默认选中当前角色拥有的权限. 问题:第一次点击编辑按钮时,不会选 ...
- [转]vue Element UI走马灯组件重写
https://blog.csdn.net/u013750989/article/details/82885482 1.element ui走马灯组件 -- carousel分析一波源代码:carou ...
- 基于 vue+element ui 的cdn网站(多页面,都是各种demo)
前言:这个网站持续更新中...,有网上预览,github上也有源码,喜欢记得star哦,欢迎留言讨论. 网站地址:我的个人vue+element ui demo网站 github地址:yuleGH g ...
随机推荐
- 隐马尔可夫模型(HMM)及Viterbi算法
HMM简介 对于算法爱好者来说,隐马尔可夫模型的大名那是如雷贯耳.那么,这个模型到底长什么样?具体的原理又是什么呢?有什么具体的应用场景呢?本文将会解答这些疑惑. 本文将通过具体形象的例子来引入该模型 ...
- 使用Xmanager分析Java内存情况
今天是想看下程序在正式环境中,内存使用回收的情况,于是开始. 1.首先下载Xmanager,Xshell,然后在Xshell-设置-隧道中设置转发X11连接到Xmanager: 2.开始布置Linux ...
- sql慢查询工具(配置代码)
# 在mysql的配置文件/etc/mysql/mysql.conf.d/mysqld.cnf[mysqld]中配置懒查询 slow_query_log = ON # 是否已经开启慢查询 long_q ...
- Spring Boot快速集成kaptcha生成验证码
Kaptcha是一个非常实用的验证码生成工具,可以通过配置生成多样化的验证码,以图片的形式显示,从而无法进行复制粘贴:下面将详细介绍下Spring Boot快速集成kaptcha生成验证码的过程. 本 ...
- Java的23种设计模式,详细讲解(三)
本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...
- ThreadLocal(线程本地存储)
1. ThreadLocal,即线程本地变量或线程本地存储. threadlocal的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或组件之间一些公共变量传递的 ...
- 何为http?何为RPC?
RPC(即Remote Procedure Call,远程过程调用)和HTTP(HyperText Transfer Protocol,超文本传输协议)他们最本质的区别,就是RPC主要工作在TCP协议 ...
- find命令通过排序只保留最新的文件目录
find /usr/local/canal/logs/example -type d -name "*-*" | sort -nr | awk '{if (NR>=2){pr ...
- 微信小程序和支付宝小程序富文本使用
微信小程序使用的是 1. wxml 页面元素的最简单使用 <rich-text nodes="{{这是你的数据}}"></rich-text> 2. j ...
- VM虚拟机Android安装图形界面
摘自,转 https://blog.csdn.net/weixin_42633191/article/details/89391188