最近公司老項目改用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的保持一致。