使用场景
使用a-upload提交文件时,往往会携带其他需要手动输入的信息,a-upload组件本身虽然提供了上传前校验的方法beforeUpload,但该方法是在选择文件后才会进行,这是官方文档的描述:
上传文件之前的钩子,参数为上传的文件,若返回 false 则停止上传。支持返回一个 Promise 对象,Promise 对象 reject 时则停止上传,resolve 时开始上传( resolve 传入 File 或 Blob 对象则上传 resolve 传入对象)。注意:IE9 不支持该方法。
如果用户想要在选择上传文件之前校验(如input输入框的内容是否符合规则)则该方法无法支持
解决思路
用@change方法监控需要校验的内容,当内容不通过校验时上传按钮不启用,通过校验后点击上传按钮才可以上传文件
注意事项
onChange方法中不要使用vue的双向绑定获取校验内容,因为onChange触发时的实际内容为输入前的值,由此可见这样都比较不好,所以antd给你提供了e,目的就是想让你当前输入用e.target.value来获取 而不是用getFieldValue获取当前输入值。
实现代码
页面部分代码
<a-form :form="excelform" autocomplete="off">
<!-- 示例,上传文件前要校验姓名电话必须填写 -->
<a-form-item :md="8" :sm="24" label="姓名">
<a-input @change="checkUpload($event.target.value, 0)" :v-model="username" name="username" />
</a-form-item>
<a-form-item :md="8" :sm="24" label="电话">
<a-input @change="checkUpload($event.target.value, 1)" :v-model="usertel" maxLength="11" name="usertel" />
</a-form-item>
</a-form>
<!-- 未通过校验时,按钮点击功能为校验和提示,已通过校验是按钮功能为上传,使用同一个标志位来控制两个不同功能的按钮不会一起显示 -->
<a-button v-show="!isUpload" type="primary" style="margin-bottom:10px;" @click="beforeUploadCheck">excel导入</a-button>
<a-upload v-show="isUpload" accept=".xls,.xlsx" :showUploadList="false" :customRequest="selfUpload" :beforeUpload="beforeUpload" ref="upload">
<a-button ref="beforeUpload" type="primary" style="margin-bottom:10px;">excel导入</a-button>
</a-upload>
onChange监听部分代码
checkUpload(value, type) {
//由于运营商在不断申请新号段,实际项目中不建议将手机号校验做的太过细致
var moblieCheck = /^1\d{10}$/;
if(type == 1){
if(this.username == null || this.username == ''){
this.isUpload = false;
return ;
}
if(!moblieCheck.test(value)){ //此处不要使用vue的双向绑定获取当前内容,使用@change传递的数据
this.isUpload = false;
return ;
}
}else{
if(value == null || value == ''){ //此处不要使用vue的双向绑定获取当前内容,使用@change传递的数据
this.isUpload = false;
return ;
}
if(!moblieCheck.test(this.usertel)){
this.isUpload = false;
return ;
}
}
this.isUpload = true;
},
校验和提示部分代码
beforeUploadCheck(){
if(this.username == null || this.username == ''){
this.isUpload = false;
this.$message.error('姓名必须填写');
return ;
}
//由于运营商在不断申请新号段,实际项目中不建议将手机号校验做的太过细致
var moblieCheck = /^1\d{10}$/;
if(!moblieCheck.test(this.usertel)){
this.isUpload = false;
this.$message.error('电话号码格式不正确');
return ;
}
}
校验文件,这里是校验文件是excel
beforeUpload(file) {
const isExcel =
file.type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || file.type == 'application/vnd.ms-excel';
//此处需要特别注意,使用file.type进行校验是不可靠的,并非所有系统和浏览器都能获取file.type的信息,比如同为chrome,在mac环境是无法获取到file.type的
var suffix = file.name.substr(file.name.lastIndexOf("."));
if (!isExcel && (".xls" != suffix && ".xlsx" != suffix)) {
this.$message.error('请上传excel文件');
}
const isLt2M = file.size / 1024 < 20000 && file.size / 1024 > 5;
if (!isLt2M) {
this.$message.error('文件大小应在10KB~20MB之间');
}
return isExcel && isLt2M;
}
上传文件方法
selfUpload({ action, file, onSuccess, onError, onProgress }) {
let formData = new FormData();
formData.append('file', file);
formData.append('username', this.username);
formData.append('usertel', this.usertel);
excelUpload(formData) //上传文件的js,这里不放出了
.then(res => {
if (res == 200) {
this.$message.success('操作成功');
}else{
this.$message.error('操作失败');
}
})
.finally(() => {
//处理无论成功失败必定进行的代码
});
}
后记
作为adnt框架的新手,在想到需要选择文件前进行校验的需求后查阅官方文档并没有得到满意的结果,于是自己想出了这么一个“偏门”的解决方案达到了近似的效果