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 ...
随机推荐
- kafka 重放 重播 从某个时间点或者offset开始消费
转自: https://www.jianshu.com/p/932663e9a226 consumer.subscribe(topicA); consumer.poll(100);//正常订阅topi ...
- 基于Node 的http转发demo,项目中请使用express+http-proxy-middleware
var http = require("http"); var data = ''; function getData() { const options = { host: 'w ...
- jQuery 源码分析(十三) 数据操作模块 DOM属性 详解
jQuery的属性操作模块总共有4个部分,本篇说一下第2个部分:DOM属性部分,用于修改DOM元素的属性的(属性和特性是不一样的,一般将property翻译为属性,attribute翻译为特性) DO ...
- 【51Nod1584】加权约数和(数论)
[51Nod1584]加权约数和(数论) 题面 51Nod 题解 要求的是\[\sum_{i=1}^n\sum_{j=1}^n max(i,j)\sigma(ij)\] 这个\(max\)太讨厌了,直 ...
- Elasticsearch Query DSL 语言介绍
目录 0. 引言 1. 组合查询 2. 全文搜索 2.1 Match 2.2 Match Phase 2.3 Multi Match 2.4 Query String 2.5 Simple Query ...
- Java自定义注解(1)
Java注解简介 1. Java注解(Annotation) Java注解是附加在代码中的一些元信息,用于一些工具在编译. 运行时进行解析和使用,起到说明.配置的功能. 注解相关类都包含在java.l ...
- Linux软件安装——服务管理
Linux软件安装——服务管理 摘要:本文主要学习了Linux中有关服务管理的知识. 什么是服务 服务一般是放置在后台运行的一个或多个进分程,为用户或系统提供某项特定的服务,有些是系统服务,有些则是独 ...
- DataGridView怎样实现添加、删除、上移、下移一行
场景 在Winform中使用DataGridView实现添加一行.删除一行.上移一行.下移一行. 注: 博客主页: https://blog.csdn.net/badao_liumang_qizhi ...
- H265之格式解析
头定义如下: 上一段码流: 前面 4个字节位00 00 00 01 为nul头,这个和H264是一样的. 下面两个字节为40 01 ====>二进制 0100 0000 0000 0001 F ...
- js个人笔记简记
正则表达式 创建正则表达式的两种方法: Var reg = new RegExp(‘’) Var reg = / a/ 后面三个参数g:全局匹配 i:不区分大小写 m:多行匹配 开头结尾有用 常见 ...