在调试图片限制宽高时 出现了很多的问题 一开始我直接百度google, 发现都没有这个问题.感觉这应该是很常见的需求, element内部没有实现, 也许是很简单?网上都没有此类问题.
到GitHub的issue里看, 确实有类似的问题, 但没有系统的解决方法.一开始,我的思路就是按照常规的校验方法去校验, 由于js是没有读取图片权限的, 在这里我使用了URL对象的URL.createObjectURL(file)方法, 其中包含一个表示参数中给出的对象的URL, 这个URL的生命周期和创建它的窗口中的document 绑定, 可以用于在浏览器上预览本地图片或者视频.
但是既然是通过url读取宽高就牵扯到图片是否加载完毕的问题, 虽然是在本地创建一个图片对象, 但创建还是有延迟问题.
解决了文件读取问题后我就能拿到图片真实宽高了, 经过反复的debug 我发现img.onload并没有走, isSize也一直是false, 看来这种邯郸学步的方法显然行不通, 想到onload是异步的, 来不及走就return结束了这个方法, 其实最省事的办法, 就是给图片判断加上1秒的延迟, 但这种做法显然是在自掘坟墓.所以还是需要拿到文件真实的加载完成状态, 所以想法异步操作一下, 让onload之后再执行isSize的判断以及return, 于是我就增加回调函数使onload先执行, 然后对isSize有赋值操作.代码如下:
之后isSize确实被重新赋值, 也有了正确的提示, 但只是一闪而过, 并成功的上传了???
一步步的开始debug了, 发现最后还是可以回到return的, 但是不知道原因, 接着又开始google了, 发现我的思路是错的.我发现beforeAvatarUpload其实是返回一个Promise
我在查看了一篇文章后, 发现Element Ui的upload人家内部确实是想要一个promise, 直接给isSize一个boolean值return出去其实是没有任何作用的, 这就解释了为什么可以弹出错误信息却可以成功上传了, 这个是开始的实现方法
再后来我通过查看源码之后发现this.beforeUpload是一个真正的promise, 也就是说必须返回一个promise, 简单的boolean值是没用的, 因为Element组件内部还有很多的对promise的实现.
这下清楚了一点, 就有了最终的方法, 经过多次测试终于可以了.
beforeAvatarUpload(file) {
this.filterType = []
if (this.pType) { // 判断父组件传过来的可上传图片类型
const typeArr = this.pType
for (const i in typeArr) {
this.filterType.push(this.imgType[typeArr[i]])
}
} else { // 如果没有直接赋值为默认
this.filterType = this.imgType
}
let typeFlag = false
for (const o in this.filterType) {
if (this.filterType[o] === file.type) {
typeFlag = true
}
}
const isLt1M = file.size / 1024 / 1024 < 1
if (!typeFlag) {
this.$message.error('上传图片只能是 ' + this.filterType + ' 格式!')
}
if (!isLt1M) {
this.$message.error('上传图片大小不超过 1MB')
}
const _width = 210
const _height = 100
const isSize = new Promise(function(resolve, reject) {
const _url = URL.createObjectURL(file)
const img = new Image()
if (1) { // 是否判断宽高
img.onload = function() {
const valid = img.width === _width
valid ? resolve() : reject()
}
} else {
resolve()
}
img.src = _url
}).then(() => {
return true
}, () => {
this.$message.error('上传的尺寸必须是宽:' + _width + 'px 高:' + _height + 'px')
return Promise.reject()
})
return typeFlag && isLt1M && isSize
}
当然 我这里宽高为固定的宽高, 在实际代码中可以是子组件传过来的, 如果没有传值也可以不限制, 判断那里我还没有写.这个功能看似很简单很简单, 但是其实牵扯到promise异步调用返回值, 由于以前异步基本都用在ajax请求, 并没有在别的地方用过, 所以花些时间学习了一下.