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 ...
随机推荐
- JS 从内存空间谈到垃圾回收机制
壹 ❀ 引 从事计算机相关技术工作的同学,对于内存空间相关概念多少有所耳闻,毕竟像我这种非计算机科班出身的人,对于栈堆,垃圾回收都能简单说道几句:当我明白JS 基本类型与引用类型数据存储方式不同,才 ...
- tushare+pandas实现财经数据分析
写在前面的话: 这是一个优秀的财经接口包,博主平时工作中也有使用,觉得很好,现在分享一些使用心得给需要的人,tushare并不是一个炒股软件,只是一个提供pandas数据的工具,具体如何使用,因人而异 ...
- 《细说PHP》第四版 样章 第18章 数据库抽象层PDO 10
18.8 设计完美分页类 数据记录列表几乎出现在Web项目的每个模块中,假设一张表中有十几万条记录,我们不可能一次全都显示出来,当然也不能仅显示几十条.为了解决这样的矛盾,通常在读取时设置以分页的形 ...
- Java反射方法总结
1.得到构造器的方法 Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数, Constructor[] getConstr ...
- DatabaseLibrary -数据库操作
操作数据库: Table Must Exist 验证表必须存在,存在则Pass,反之Fail Delete All Rows From Table 删除数据库中表的所有行 Execute Sql St ...
- Docker开启Remote API 访问 2375端口
Docker常见端口 我看到的常见docker端口包括: 2375:未加密的docker socket,远程root无密码访问主机2376:tls加密套接字,很可能这是您的CI服务器4243端口作为h ...
- ASP.NET(1)
1.IIS安装问题,先装VS再装IIS,处理程序映射有问题,使用VS自带的控制台输入命令,注册路径 2.开发模式,一般处理程序,使用IO操作读取html文件,使前后端分离 3.post请求和get请求 ...
- 关于.Net Core 部署在Linux下连接SqlServer数据库超时解决办法
.Net Core 在 Linux 下连接 SqlServer 需要 SqlServer2008 SP3或以上版本,或SqlServer2012,或SqlServer2014. 如果SqlServer ...
- 你以为你真的了解final吗?
本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...
- map元素area热区坐标自适应窗口大小
业务需求:点击图片热区跳转到不同的链接地址,同时要自适应窗口尺寸的变化. 问题:热区坐标点不会随着窗口调整变化 解决思路:获取初始的坐标点与图片宽高的比例,然后用比例乘以调整后的窗口宽高,就获得了新的 ...