我後端的,剛接觸vue個星期,根據需求寫了個上傳控件,很靈活的。沒有看element el-upload源碼,樣式用的element的。感受vue確實好用。vue
先看樣子:後端
<!-- 單文件上傳組件 --> <template> <div> <input type="file" id="file" hidden @change="fileChange" :accept="accept"> <div v-if="upMode=='url'" style="width: 100%;display:inline-flex;"> <el-input :value="path" disabled></el-input> <el-button size="small" type="primary" @click="btnChange">{{autoUpload?label:'選擇文件'}}</el-button> <el-button v-if="!autoUpload && loadButton" size="small" type="success" @click="uploadClick">{{label}}</el-button> </div> <div v-else-if="upMode=='head'" class="upmode-head"> <div class="el-upload el-upload--picture-card" @click="btnChange"> <i v-if="path==''" class="el-icon-plus"></i> <img v-else :src="path"> </div> <el-button v-if="!autoUpload && loadButton" size="small" type="success" @click="uploadClick">{{label}}</el-button> </div> <div v-else-if="upMode=='variable'" class="el-upload-dragger" @click="btnChange"> <div v-if="path==''"> <i class="el-icon-upload"></i><div class="el-upload__text"><em>{{label}}</em></div> </div> <img v-else :src="path"> </div> </div> </template> <script> import glob from '@/utils/global.js' export default { model: { prop: 'path', event: 'onsuccess' }, props: { label: {type: String, default: '上傳'},//按鈕文字 accept: {String,default:'image/jpeg,image/png,image/x-icon'},//預選文件類型 autoUpload:{type:Boolean, default:true},//是否自動上傳 loadButton:{type:Boolean, default:true},//手動上傳時是否生成上傳按鈕 path:String,//回顯地址 action: {type: String, default: '/api/upload/img'},//傳入action能夠調用不一樣接口適應不一樣文件類型上傳 upMode:{type: String, default: 'url'},//上傳控件模式url,head,variable }, methods: { btnChange() { var file = document.getElementById('file'); file.click(); }, fileChange(e){ try { const fu = this.getFile(); if(fu==null)return; if(!this.beforeUpload(fu))return; if(this.autoUpload){ this.submit(fu); }else{ if(this.upMode=='url')return; //本地預覽 var reader = new FileReader(); reader.readAsDataURL(fu); reader.onload = function(e) { var src = this.result; var str = '<img src="'+src+'">'; var target=this.upMode=='head'?'.el-upload--picture-card':'.el-upload-dragger'; var nim = document.querySelector(target); if(nim) { nim.innerHTML=''; nim.insertAdjacentHTML("beforeEnd", str) } }; } } catch (error) { console.debug('choice file err:',error); } }, beforeUpload(f) { const maxSzie = glob.Config.UploadSize; if (f.size/1024/1024 > maxSzie) { this.$message.error('上傳文件大小不能超過'+maxSzie+'M.'); return false; } var types = glob.Config.UploadType; for (let i = 0; i < types.length; i++) { if(types[i]===f.type) return true; } this.$message.error('上傳文件格式不容許!'); return false; }, uploadClick(e){ this.submit(); }, submit(file){ try { if(!file) file = this.getFile(); if(file==null)return; var isUpload =true; this.$emit('onbefore', file); if(!isUpload)return; const url =process.env.Store_API + this.action; var fd = new window.FormData(); // 配置post請求的參數。參數名fileType,值爲category(看後端的具體要求) fd.append('fileType', 'category'); fd.append('file', file); var xhr = new XMLHttpRequest(); xhr.open('POST', url, true); xhr.send(fd); xhr.onload = () => { if (xhr.status === 200) { var res = JSON.parse(xhr.responseText); if(res.code==1) { var imgurl = glob.StaticStoreHost+res.data; this.$emit('onsuccess', imgurl); }else{ this.$message(res.message); } } } } catch (error) { console.debug('upload file err:',error); } }, getFile(){ var file = document.getElementById('file'); if(file.files.length==0){ this.$message('沒有選擇文件'); return null; } return file.files[0]; }, }, } </script>
其實就這個小組件就體現到封裝、繼承、多態的思想,多花時間思考,代碼就能簡潔、靈活、可用性高。api
樣式也有重寫,須要樣式的評論支持下,謝謝。app