今天在寫設(shè)置界面的時(shí)候,遇見了更換圖標(biāo)這種類型的問題!感覺好熟悉,自己在寫軟件編輯的時(shí)候好像寫個(gè)類似的功能,心里還有些后悔,直接引這里的不就好了嘛,自己寫搞得多此一舉。然而我試圖檢驗(yàn)一下功能的完整性。結(jié)果:

我擦,這是什么鬼?馬上看了下代碼邏輯,我去,頓時(shí)有想殺人的沖動(dòng)----連個(gè)click都沒有,靜態(tài)頁面?。『冒?,不過幸好我之前寫過類似的功能。立馬高效很多,復(fù)用是一個(gè)程序員的基本素養(yǎng)。當(dāng)然首先vue就秉承的是組件化系統(tǒng),將每一個(gè)相同和和類似的功能抽象成組件,減少代碼的重用和耦合,(PS:一寫到這幾句話,咋頭腦中閃現(xiàn)了面向?qū)ο?,封裝,原型鏈。。。),竟然用vue,那就來實(shí)踐框架的精髓。
上傳我們需要控制的是上傳參數(shù),當(dāng)然請(qǐng)求都一樣,沒有后臺(tái)約定的必要參數(shù)你的請(qǐng)求也請(qǐng)求不通。我們部門基本上上傳約定的必須參數(shù)是文件的md5值,那么問題來了,之前提到MD5不都是后臺(tái)給的嗎?為啥后臺(tái)先向我要!對(duì),需要前端去計(jì)算MD5值,然后傳給后端進(jìn)行上傳請(qǐng)求。所以組件里首先得有個(gè)計(jì)算md5的函數(shù),我們?cè)傧胂脒€需要些什么,上傳文件總應(yīng)該有些準(zhǔn)備文件還有上傳完成吧!所以向外面暴露兩個(gè)API函數(shù),一個(gè)是上傳文件之前l(fā)ogoBe'foreUpload函數(shù),這個(gè)函數(shù)主要是操作一些上傳之前要干的事;另一個(gè)是上傳完成之后logoUploadSucess函數(shù),用來做一些logo的替換,或者加上logo的名字等等,所以我們這里要把處理完成的file對(duì)象emit出去。當(dāng)然一些props,看你的需要,根據(jù)你的需要去書寫,這里只是談一些思路。
好了!上面是對(duì)我業(yè)務(wù)的分析完成,開始封組件,這里ul我直接借用了element。我先把代碼貼出來
<template>
<div>
<el-upload :before-upload="logoBeforeUpload" :show-file-list="false" :on-success="logoUploadSucess" :action="url"
:data="postData">
<el-button>瀏覽</el-button>
</el-upload>
</div>
</template>
<script>
import SparkMD5 from 'spark-md5/spark-md5.min';
export default {
props: {
url: {
type: String
},
postData: {
type: Object,
default: function() {
return {
md5: ''
}
}
}
},
data() {
return {
}
},
methods: {
// 圖片上傳之前
logoBeforeUpload(file) {
const self = this
// 當(dāng)文件上傳之前必須返回false或promise才能阻止文件上傳,當(dāng)我們對(duì)文件進(jìn)行配置后,我們需要繼續(xù)運(yùn)行所以通過promise的resolve
return new Promise((resolve, reject) => {
self.fileMd5Calculate(file, (md5) => {
console.log(md5);
self.$set(self.postData, 'md5', md5)
// self.postData.md5 = md5
resolve()
})
})
},
// 圖片上傳成功之后
logoUploadSucess(e, file) {
// this.pngName = file.name
// this.logoUrl = file.url
this.$emit('success', file)
},
// 計(jì)算MD5值
fileMd5Calculate(file, callBack) {
console.log('file', file)
let chunkSize = 1024 * 1024;
this.fileReader = new FileReader();
let chunks = Math.ceil(file.size / chunkSize),
blobSlice =
File.prototype.slice ||
File.prototype.mozSlice ||
File.prototype.webkitSlice,
currentChunk = 0,
spark = new SparkMD5.ArrayBuffer(),
fileReader = new FileReader();
console.log('spark', spark);
console.log('fileReader', fileReader);
console.log(11111);
fileReader.onload = function(e) {
spark.append(e.target.result);
currentChunk++;
if (currentChunk < chunks) {
loadNext();
} else {
callBack(spark.end());
}
};
fileReader.onerror = function() {
console.warn('錯(cuò)誤');
};
function loadNext() {
let start = currentChunk * chunkSize,
end = start + chunkSize >= file.size ? file.size : start + chunkSize;
fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
}
console.log(22222);
loadNext();
}
}
}
</script>
<style scoped>
</style>
看代碼可以看出我需要父組件傳進(jìn)來的是服務(wù)器地址,上傳參數(shù)!當(dāng)然這看每個(gè)人需要,需要啥傳啥就行。
首先計(jì)算文件MD5我用的是spark-md5.js,因?yàn)榕聢D片太大(也可能想多了,圖片一般沒有多大)我采取了分片計(jì)算md5的方法。計(jì)算md5完成后通過回調(diào)函數(shù)傳出,在圖片上傳之前傳出我們調(diào)用這個(gè)函數(shù),然后配置上傳參數(shù)。然后其實(shí)就到圖片上傳完成之后了,完成之后的操作肯定是通過父組件完成,我們把file對(duì)象傳到父組件,給父組件綁定success方法
<upload-img class="img-upload" url="/sfmgapi/upload/add" @success="canSucess"></upload-img>
canSucess(file) {
this.pngName = file.name;
this.logoUrl = file.url;
},
我在父組件定義的canSuccess,這里我做的操作比較簡單就是通過圖片地址改變圖片,同時(shí)改變圖片的名字。這里也看你怎么玩!

當(dāng)然我得通過這個(gè)組件把設(shè)置中的圖片換掉所以引用即可