最近公司老项目改用vue开发,前端框架采用element ui,这个框架风格还是很漂亮的,只是上传功能有一些问题,比如:limit=1限制上传数量后,后面的添加按钮没有隐藏,再用就是如果上传图片组,很多需求需要对图片组进行排序修改,基于这两个需求,对element的el-upload组件进行了二次封装。
首先引入sortable.js这个插件,这个是一个很强大的排序插件,下面直接上我封装的上传代码
组件的html部分:
<template id='example'>
<div>
<el-upload :action="elAction"
:ext="elExt"
:data="elData"
:file-list="elFileList"
:limit="elLimit"
:on-exceed="onElExceed"
:before-upload="beforeElUpload"
:on-remove="onElRemove"
:before-remove="beforeElRemove"
:on-success="onElSuccess"
:on-error="onElError"
:on-change="onElChange"
:list-type="elListType"
:on-preview="pictureCardPreview"
:class="{elExceed:checkLimit}">
<i class="el-icon-plus" v-if="isImage"></i>
<el-button size="small" type="primary" v-else>点击上传</el-button>
</el-upload>
<el-dialog :visible.sync="dialogVisible" size="tiny" v-if="isImage">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
</div>
</template>
组件的注册js
Vue.component('pa-upload', {
template: '#example',
props: {
data: Object,
limit: {
type:Number,
default:0
},
fileList: Array,
ext: {
type: String,
default: ".jpg,.png,.gif"
},
maxSize: {
type: Number,
default: 1204
},
action:String,
listType: {
type: String,
default: "picture-card"
},
sortable: { type: Boolean, default: false },
onPreview: { type: Function, default: function () { } },
onRemove: { type: Function, default: function () { } },
onSuccess: { type: Function, default: function () { } },
onError: { type: Function, default: function () { } },
onProgress: { type: Function, default: function () { } },
onChange: { type: Function, default: function () { } },
beforeUpload: { type: Function, default: function () { return true;}},
beforeRemove: { type: Function, default: function () { return true;}},
},
data: function(){
return {
dialogImageUrl: "",
dialogVisible: false,
elAction: this.action,
elSortable: this.sortable,
elCount:0,
elData:this.data,
elFileList: this.fileList,
elLimit: this.limit,
elExt: this.ext,
elMaxSize: this.maxSize,
elListType: this.listType,
}
},
created: function ()
{
this.elCount = this.elFileList.length;
},
mounted: function () {
var that = this;
if (this.elSortable)
{
var list = this.$el.querySelector('.el-upload-list');
new Sortable(list, {
onEnd: function (ev) {
var arr = that.elFileList;
arr[ev.oldIndex] = arr.splice(ev.newIndex, 1, arr[ev.oldIndex])[0];
},
});
}
},
computed: {
checkLimit: function () {
//console.log(this.elLimit > 0 && this.elCount >= this.elLimit)
return (this.elLimit > 0 && this.elCount >= this.elLimit)
},
isImage: function () {
return this.elListType == "picture-card";
},
},
watch: {
elFileList: {
handler(newName, oldName) {
//console.log(this.elFileList);
this.$emit('input', JSON.stringify(newName));//传值给父组件, 让父组件监听到这个变化
},
immediate:true // 代表在wacth里声明了firstName这个属性之后立即先去执行handler方法
}
},
methods: {
beforeElUpload: function (file)
{
console.log("beforeUpload");
var ext = this.elExt;
var maxSize = this.elMaxSize;
var isOkExt = ext.indexOf(file.name.substring(file.name.lastIndexOf('.'))) >= 0;
if (!isOkExt) {
this.$message.error('只能上传' + ext + '格式的文件');
return false;
}
var isLtmaxWidth = file.size / 1024 < maxSize;
if (!isLtmaxWidth) {
this.$message.error('上传文件大小不能超过' + maxSize + 'KB!');
return false;
}
return this.beforeUpload(file);
},
onElSuccess: function (response, file, fileList)
{
this.elCount = fileList.length;
response.name = file.name;
response.url = file.url;
this.elFileList.push(response);
this.onSuccess(response, file, fileList);
},
onElError: function (err, file, fileList) {
this.onError(err, file, fileList);
},
onElChange: function (file, fileList) {
this.onChange(file, fileList);
},
onElProgress: function (event, file, fileList)
{
this.onProgress(event, file, fileList);
},
onElRemove:function(file, fileList)
{
this.elCount = fileList.length;
this.elFileList = fileList;
this.onRemove(file, fileList);
},
beforeElRemove: function (file, fileList)
{
return this.beforeRemove(file, fileList);
},
onElExceed: function (files, fileList)
{
this.$message.error('只能上传' + this.elLimit + '个文件!');
},
pictureCardPreview:function(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
}
}
})
组件的使用:
<pa-upload action="/e/upload/"
:data="{}"
:file-list="[{id:1,name:'1.jpg',url:'/upload/test.png'}]"
ext=".jpg,.png,.docx"
:max-size="1024"
:sortable="true"
list-type="picture-card"
v-model="image"
:limit="5">
</pa-upload>
ext:允许上传的格式
max-size:最大上传尺寸,单位kb
sortable:是否允许拖动排序
v-model:和data中的属性绑定,实现双向绑定。
其他属性和element的保持一致。