效果图:

在这里插入图片描述

步骤

首先,定义一个 el-upload 的组件,这里我选择的是「手动上传」模式:

<el-upload
    action=""
    :before-upload="beforeUpload"
    ref="uploadFile"
    :on-remove="removeFile"
    :file-list.sync="fileList">
    <el-button size="small" type="primary" plain>选取文件</el-button>
    <el-button size="small" type="success" @click="submit">上传文件</el-button>
</el-upload>

通过阅读 ElementUI 的源码,可以得知他的进度条以及右侧的小对勾分别是通过 file.percentage 和 file.status 来控制的。percentage 就是进度的百分比,是一个 0 ~ 100 的数字。status 有四种状态, ready:准备上传、uploading:正在上传、success:上传成功、fail:上传失败。
在上传文件时,我们不用 ElementUI 自带的上传方法,而是在 before-upload 中做处理,因此每次都返回 return false,以阻止调用自带的上传方法。

beforeUpload(newFile) {
    this.fileList.push({
        name: newFile.name,
        url: '',
        file: newFile,
        status: 'ready',
        percentage: 0
    });
    return false;
}

这里还发现了 ElementUI 的一个 BUG,就是点击删除文件时,文件在列表中消失了,但是在 this.fileList 中仍然存在,因此需要单独处理一下:

removeFile(file, fileList) {
    if (file.hasOwnProperty('file')) {
        for (let index in this.fileList) {
            if (this.fileList[index].uid === file.uid) {
                this.fileList.splice(index, 1);
                return;
            }
        }
    }
}

利用 axios 执行上传请求时,我们可以通过它提供的 onUploadProgress 方法获取到上传进度:

upload(url, params = {}, onUploadProgress, callback) {
	axios({
		headers: { 'X-Requested-With': 'XMLHttpRequest' },
		method: 'post',
		url: url,
		data: params,
		onUploadProgress,
	}).then((resp) => {
		callback({ status: 'success', data: resp });
	}).catch((error) => {
		callback({ status: 'error', error: error });
	});
}

接下来就是上传文件的操作了:

let readyFile = null;
for (const file of this.fileList) {
    if (file.status === 'uploading') {
        return this.$message.error('已有文件正在上传');;
    }
    if (file.status === 'ready') {
        readyFile = file;
    }
}
if (!readyFile) {
    return this.$message.error('请选取文件');
}
this.uploadingFile = readyFile;
this.uploadingFile.status = 'uploading';
const url = 'xxx';
let params = new FormData();
params.append('file', readyFile.file);
const onUploadProgress = (progressEvent) => {
    let percent = (progressEvent.loaded / progressEvent.total * 100 || 0);
    this.uploadingFile.percentage = percent;
};
this.upload(url, params, onUploadProgress, (resp: any) => {
    if (resp.status === 'success') {
        const data = resp.data.data;
        if (data.status === 'success') {
            this.$message({
                type: 'success',
                message: '上传成功',
            });
            this.uploadingFile.status = 'success';
        } else {
            this.uploadingFile.status = 'ready';
            this.uploadingFile.percentage = 0;
            this.$message.error(data.data.fail_message');
        }
    } else {
        this.uploadingFile.status = 'ready';
        this.uploadingFile.percentage = 0;
        const error = resp.error;
        this.$message.error(error.response.data.message);
    }
});
GitHub 加速计划 / eleme / element
54.06 K
14.63 K
下载
A Vue.js 2.0 UI Toolkit for Web
最近提交(Master分支:3 个月前 )
c345bb45 7 个月前
a07f3a59 * Update transition.md * Update table.md * Update transition.md * Update table.md * Update transition.md * Update table.md * Update table.md * Update transition.md * Update popover.md 7 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐