今天在写设置界面的时候,遇见了更换图标这种类型的问题!感觉好熟悉,自己在写软件编辑的时候好像写个类似的功能,心里还有些后悔,直接引这里的不就好了嘛,自己写搞得多此一举。然而我试图检验一下功能的完整性。结果:
我擦,这是什么鬼?马上看了下代码逻辑,我去,顿时有想杀人的冲动----连个click都没有,静态页面!!好吧,不过幸好我之前写过类似的功能。立马高效很多,复用是一个程序员的基本素养。当然首先vue就秉承的是组件化系统,将每一个相同和和类似的功能抽象成组件,减少代码的重用和耦合,(PS:一写到这几句话,咋头脑中闪现了面向对象,封装,原型链。。。),竟然用vue,那就来实践框架的精髓。
上传我们需要控制的是上传参数,当然请求都一样,没有后台约定的必要参数你的请求也请求不通。我们部门基本上上传约定的必须参数是文件的md5值,那么问题来了,之前提到MD5不都是后台给的吗?为啥后台先向我要!对,需要前端去计算MD5值,然后传给后端进行上传请求。所以组件里首先得有个计算md5的函数,我们再想想还需要些什么,上传文件总应该有些准备文件还有上传完成吧!所以向外面暴露两个API函数,一个是上传文件之前logoBe'foreUpload函数,这个函数主要是操作一些上传之前要干的事;另一个是上传完成之后logoUploadSucess函数,用来做一些logo的替换,或者加上logo的名字等等,所以我们这里要把处理完成的file对象emit出去。当然一些props,看你的需要,根据你的需要去书写,这里只是谈一些思路。
好了!上面是对我业务的分析完成,开始封组件,这里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
// 当文件上传之前必须返回false或promise才能阻止文件上传,当我们对文件进行配置后,我们需要继续运行所以通过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)
},
// 计算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('错误');
};
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>
看代码可以看出我需要父组件传进来的是服务器地址,上传参数!当然这看每个人需要,需要啥传啥就行。
首先计算文件MD5我用的是spark-md5.js,因为怕图片太大(也可能想多了,图片一般没有多大)我采取了分片计算md5的方法。计算md5完成后通过回调函数传出,在图片上传之前传出我们调用这个函数,然后配置上传参数。然后其实就到图片上传完成之后了,完成之后的操作肯定是通过父组件完成,我们把file对象传到父组件,给父组件绑定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,这里我做的操作比较简单就是通过图片地址改变图片,同时改变图片的名字。这里也看你怎么玩!
当然我得通过这个组件把设置中的图片换掉所以引用即可