element ui upload上传文件功能

1,626 阅读1分钟

一、upload上传文件及表单,且显示列表(单个)

功能:1、上传文件校验 2、随表单一块提交 3、文件列表展示 4、列表删除后文件联动

效果图:

代码:

父组件:

<template>
    <div class="form-page">
        <el-button @click="addItem">新建</el-button>
<!--        <el-button @click="addItem">编辑</el-button>-->
        <!--新建-->
        <newEditForm ref="addForm" :dialogVisible.sync="dialogVisible" @save="save"></newEditForm>
    </div>
</template>

<script>
    import newEditForm from '../components/formDialog7'

    export default {
        name: "formDemo7",
        data() {
            return {
                dialogVisible: false
            }
        },
        components: {
            newEditForm
        },
        methods: {
            addItem() {
                this.dialogVisible = true;
                this.$nextTick(() => {
                    this.$refs.addForm.resetForm();
                })

            },
            save(data) {
                console.log(data);
            }
        }
    }
</script>

<style lang="less" scoped>
    .formDemo-page {
        text-align: left;
    }
</style>

子组件:

<template>
    <!--功能(单个文件):1、上传文件校验 2、随表单一块提交 3、文件列表展示 4、列表删除后文件联动 -->
    <el-dialog
            title="提示"
            :visible="dialogVisible"
            :close-on-click-modal="false"
            :close-on-press-escape="false"
            @update:visible="changeVisible()"
            width="30%">
        <el-form ref="form" :model="form" label-width="80px" :rules="rules">
            <el-form-item label="名称" prop="name">
                <el-input v-model="form.name"></el-input>
            </el-form-item>
            <el-form-item label="上传文件" prop="file">
                <el-upload
                        class="upload-demo"
                        drag
                        action=""
                        accept=".txt,.jpg"
                        :on-change="handleChange"
                        :auto-upload="false"
                        :file-list="form.file"
                        :on-remove="handleAddRemove"
                >
                    <i class="el-icon-upload"></i>
                    <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
                    <div class="el-upload__tip" slot="tip">只能上传txt/jpg文件,且不超过5kb</div>
                </el-upload>
            </el-form-item>
        </el-form>
        <span slot="footer" class="dialog-footer">
            <el-button @click="changeVisible()">取 消</el-button>
            <el-button type="primary" @click="save()">确 定</el-button>
        </span>
    </el-dialog>

</template>

<script>
    export default {
        name: "formDialog7",
        props: ['dialogVisible'],
        data() {
            return {
                form: {
                    name: '',
                    file: []
                },
                rules: {
                    name: [{required: true, message: '请输入名称', trigger: 'blur'}],
                    file: [{required: true, validator: this.validateFile}],
                }

            }
        },
        methods: {
            resetForm() {
                this.$refs.form.resetFields();
            },
            // 取消
            changeVisible(value = false) {
                this.$emit('update:dialogVisible', value)
            },
            // 改变文件
            handleChange(file, fileList) {
                // 个人理解:this.form.file是已有列表,fileList是已有列表加上新加的文件,需手动赋值处理;
                // 如果不处理,已有列表会自动显示fileList(检测到this.form.file变化就显示this.form.file,否则显示fileList)
                this.form.file = [file];
                this.$refs.form.validateField('file', (err) => {
                    if (err) {
                        //文件校验不通过,列表删除最后一个
                        this.form.file = fileList;
                        this.form.file.splice(-1, 1);
                    }
                });
            },
            //移除文件
            handleAddRemove(file, fileList) {
                //仅支持单个文件时
                this.form.file = fileList;
            },
            save() {
                if (!this.validate()) return;
                this.$emit('save', this.form)
            },
            // 自定义文件校验规则
            validateFile(rule, value, callback) {
                let file = this.form.file[0];
                if (!file) {
                    callback(new Error('请上传文件'));
                    return false;
                }
                //file格式及大小校验
                const validName = file.name.endsWith('.txt') || file.name.endsWith('.jpg');
                const validSize = file.size < (1024 * 5);
                if (!validName) {
                    callback(new Error('文件类型不正确'));
                } else if (!validSize) {
                    callback(new Error('文件大小超出限制'));
                } else {
                    callback();
                }
            },
            validate() {
                let result = false;
                this.$refs.form.validate((valid) => {
                    result = valid;
                })
                return result;
            }
        }
    }
</script>

<style lang="less" scoped>

</style>

before-upload和auto-upload是互斥的,当auto-upload是false的时候,before-upload事件是没作用的,所以使用on-change事件来代替。

二、upload上传文件及表单,且显示列表(多个)

功能(多个文件): 1、上传文件校验 2、随表单一块提交 3、文件列表展示 4、列表删除后文件联动5、支持多个文件上传且分别校验 6、去掉列表展示的动画效果

效果:

父组件:

<template>
    <div class="form-page">
        <el-button @click="addItem">新建</el-button>
        <!--新建-->
        <newEditForm ref="addForm" :dialogVisible.sync="dialogVisible" @save="save"></newEditForm>
    </div>
</template>

<script>
    import newEditForm from '../components/formDialog7-1'

    export default {
        name: "formDemo7-1",
        data() {
            return {
                dialogVisible: false
            }
        },
        components: {
            newEditForm
        },
        methods: {
            addItem() {
                this.dialogVisible = true;
                this.$nextTick(() => {
                    this.$refs.addForm.resetForm();
                })
            },
            save(data) {
                console.log(data);
            }
        }
    }
</script>

<style lang="less" scoped>
    .formDemo-page {
        text-align: left;
    }
</style>

子组件:

<template>
    <div class="formDialog7-1">
        <!--功能(多个文件):1、上传文件校验 2、随表单一块提交 3、文件列表展示 4、列表删除后文件联动
        5、支持多个文件上传且分别校验 6、去掉列表展示的动画效果-->
        <el-dialog
                title="提示"
                :visible="dialogVisible"
                :close-on-click-modal="false"
                :close-on-press-escape="false"
                @update:visible="changeVisible()"
                width="30%">
            <el-form ref="form" :model="form" label-width="80px" :rules="rules">
                <el-form-item label="名称" prop="name">
                    <el-input v-model="form.name"></el-input>
                </el-form-item>
                <el-form-item label="上传文件" class="is-required">
                    <el-upload
                            class="upload-demo"
                            drag
                            action=""
                            accept=".txt,.jpg"
                            :on-change="handleChange"
                            :auto-upload="false"
                            :file-list="form.file"
                            :on-remove="handleAddRemove"
                            multiple
                    >
                        <i class="el-icon-upload"></i>
                        <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
                        <div class="el-upload__tip" slot="tip">只能上传txt/jpg文件,且不超过5kb</div>
                    </el-upload>
                    <!--文件校验提示信息,在添加el-form-item中class="is-required"-->
                    <div class="file-error" v-show="errFileMsg">{{errFileMsg}}</div>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
            <el-button @click="changeVisible()">取 消</el-button>
            <el-button type="primary" @click="save()">确 定</el-button>
        </span>
        </el-dialog>
    </div>
</template>

<script>
    export default {
        name: "formDialog7-1",
        props: ['dialogVisible'],
        data() {
            return {
                form: {
                    name: '',
                    file: []
                },
                rules: {
                    name: [{required: true, message: '请输入名称', trigger: 'blur'}],
                },
                errFileMsg: ''

            }
        },
        methods: {
            resetForm() {
                this.$refs.form.resetFields();
                this.errFileMsg = '';
            },
            // 取消
            changeVisible(value = false) {
                this.$emit('update:dialogVisible', value)
            },
            // 改变文件
            handleChange(file, fileList) {
                // 个人理解:this.form.file是已有列表,fileList是已有列表加上新加的文件,需手动赋值处理;
                // 如果不处理,已有列表会自动显示fileList(检测到this.form.file变化就显示this.form.file,否则显示fileList)

                //场景一:用message提示信息最方便
                if (this.validateFile(file)) {
                    //校验通过
                    this.form.file.push(file);
                } else {
                    //手动更新
                    this.form.file.splice();
                }

                //场景二:如果非要在错误信息出显示提醒
                // let flag = true;
                // this.form.file = [];
                // for (let file of fileList) {
                //     if (this.validateFile(file)) {
                //         //校验通过
                //         this.form.file.push(file);
                //     } else {
                //         //手动更新
                //         this.form.file.splice();
                //         flag = false;
                //     }
                // }
                // if (flag) {
                //     this.errFileMsg = ''
                // }
            },
            //移除文件
            handleAddRemove(file, fileList) {
                this.form.file = fileList;
            },
            save() {
                const fileLength = this.form.file.length;
                this.errFileMsg = fileLength === 0 ? '请上传文件' : '';
                if (!this.validate() || fileLength === 0) return;
                this.$emit('save', {...this.form})
            },
            // 文件校验
            validateFile(file) {
                //场景一:用提示信息最方便,场景二注释
                this.errFileMsg = '';
                if (!file) {
                    //场景一:用提示信息最方便
                    this.$message.error('请上传文件')
                    // 场景二:如果非要在错误信息出显示提醒
                    // this.errFileMsg = '请上传文件';
                    return false;
                }
                //file格式及大小校验
                const validName = file.name.endsWith('.txt') || file.name.endsWith('.jpg');
                const validSize = file.size < (1024 * 5);
                if (!validName) {
                    //场景一:用提示信息最方便
                    this.$message.error('文件类型不正确')
                    // 场景二:如果非要在错误信息出显示提醒
                    // this.errFileMsg = '文件类型不正确';
                    return false;
                } else if (!validSize) {
                    //场景一:用提示信息最方便
                    this.$message.error('文件大小超出限制')
                    // 场景二:如果非要在错误信息出显示提醒
                    // this.errFileMsg = '文件大小超出限制';
                    return false;
                } else {
                    return true;
                }
            },
            validate() {
                let result = false;
                this.$refs.form.validate((valid) => {
                    result = valid;
                })
                return result;
            }
        }
    }
</script>

<style lang="less" scoped>
    .formDialog7-1 {
        .file-error {
            color: #F56C6C;
            font-size: 12px;
            line-height: 1;
            padding-top: 4px;
            position: absolute;
            top: 100%;
            left: 0;
        }
        //场景:去掉列表展示的动画效果
        /deep/ .el-list-enter-active,
        /deep/ .el-list-leave-active {
            transition: none;
        }
    }
</style>

三、upload上传文件及图片,图片预览

功能:1、上传图片校验 2、随表单一块提交 3、图片预览

效果图:

代码:

<template>
    <!--功能:1、上传图片校验 2、随表单一块提交 3、图片预览 -->
    <div class="add-dialog">
        <el-form :inline="true"
                 ref="addForm"
                 :model="addForm"
                 class="demo-form-inline"
                 label-width="80px"
                 :rules="rules">
            <el-form-item label="姓名:" prop="name">
                <el-input style="width:100px;" v-model="addForm.name" placeholder="请输入姓名"></el-input>
            </el-form-item>
            <el-form-item label="性别:" label-width="80px" prop="sex">
                <el-select style="width:150px;" v-model="addForm.sex" placeholder="请选择">
                    <el-option label="男" value="1"></el-option>
                    <el-option label="女" value="2"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="年龄:" label-width="80px" prop="age">
                <el-input style="width:150px;" v-model.number="addForm.age" placeholder="请输入"></el-input>
            </el-form-item>
            <!--头像-->
            <el-form-item label="组头像" prop="file" class="upload-img-form" ref="uploadElement">
                <el-upload
                        class="avatar-uploader"
                        action=" "
                        :show-file-list="false"
                        :on-change="handlePictureCardPreview"
                        :before-upload="beforeupload"
                        :limit="1"
                >
                    <img v-if="imageUrl" :src="imageUrl" class="avatar">
                    <i v-else class="el-icon-plus avatar-uploader-icon"></i>

                    <!-- <i v-show="!imageUrl" class="el-icon-upload avatar-uploader-icon"></i>-->
                    <!-- <div v-show="!imageUrl" slot="tip" class="el-upload__text upload__tip">上传照片</div>-->

                </el-upload>
            </el-form-item>
            <!--文件-->
            <el-form-item label="上传文件" prop="newFile" class="upload-file-form" ref="uploadFile">
                <el-upload
                        class="upload-demo"
                        action=""
                        :show-file-list="false"
                        :on-change="changeFile"
                        :before-upload="beforeupload"
                        :limit="1"
                        drag
                >
                    <i class="el-icon-upload"></i>
                    <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
                </el-upload>
            </el-form-item>

            <el-form-item style="text-align:center;display:block;margin-top:120px">
                <el-button type="primary" @click="onSubmit" :disabled="doSubmitFlag">保存</el-button>
            </el-form-item>
        </el-form>
    </div>
</template>

<script>
    import model from '../api/model'

    export default {
        name: 'add-dialog',
        computed: {},
        data() {
            var checkNumber = (rule, value, callback) => {
                let regEn = /^[1-9]\d*$/
                if (!regEn.test(value)) {
                    callback(new Error('正整数'))
                } else {
                    callback()
                }
            }
            return {
                imageUrl: '',
                doSubmitFlag: false,
                doUpload: false,
                addForm: {
                    name: '',
                    sex: '',
                    age: '',
                    file: '',
                    newFile: '',
                },
                rules: { // 表单验证
                    name: [
                        {required: true, message: '必填项', trigger: 'blur'}
                    ],
                    age: [
                        {required: true, message: '必填项', trigger: 'blur'},
                        {validator: checkNumber, trigger: 'blur'}
                    ],
                    sex: [
                        {required: true, message: '必填项', trigger: ['blur', 'change']}
                    ],
                    file: [
                        {required: true, message: '请上传图片'}
                    ],
                    newFile: [
                        {required: true, message: '请上传文件'}
                    ],
                },
            }
        },
        mounted() {

        },
        methods: {
            // 图片预览
            handlePictureCardPreview(file) {
                // 获取url
                this.imageUrl = URL.createObjectURL(file.raw)
                this.addForm.file = file.raw
                this.doUpload = true
                this.$refs['addForm'].validateField('file')
            },
            // 阻止upload的自己上传,进行再操作
            beforeupload(file) {
                return false
            },
            //文件
            changeFile(file) {
                this.addForm.newFile = file.raw
                this.$refs['addForm'].validateField('newFile')
            },
            // 上传
            onSubmit: function () {
                let formData = new FormData()
                this.$refs['addForm'].validate((valid) => {
                    if (valid) {
                        for (let key in this.addForm) {
                            formData.append(key, this.addForm[key])
                        }
                        this.doSubmitFlag = true
                        model.uploadFile(formData).then(res => {
                            this.doSubmitFlag = false
                        }).catch(err => {
                            this.doSubmitFlag = false
                        })
                    } else {
                        this.$message({
                            type: 'warning',
                            message: '请填写正确格式'
                        })
                        return false
                    }
                })
            },
        }
    }
</script>

<style scoped lang="less">
    .add-dialog {
        position: relative;
        width: 900px;
        height: 600px;
        margin-left: 200px;
    }

    /*上传图片样式*/
    .avatar-uploader {
        border: 1px dashed #d9d9d9;
        border-radius: 6px;
    }

    .avatar-uploader .el-upload {
        border: 1px dashed #d9d9d9;
        border-radius: 6px;
        cursor: pointer;
        position: relative;
        overflow: hidden;
    }

    .avatar-uploader .el-upload:hover {
        border-color: #409EFF;
    }

    .avatar-uploader-icon {
        font-size: 28px;
        color: #8c939d;
        width: 178px;
        height: 178px;
        line-height: 178px;
        text-align: center;
    }

    .avatar {
        width: 178px;
        height: 178px;
        display: block;
    }

</style>

四、图片回显

五、新建编辑功能复用、文件回显

效果:

父组件:

<template>
    <div class="form-page">
        <el-button @click="addItem">新建</el-button>
        <el-button @click="editItem">编辑</el-button>
        <!--新建-->
        <newEditForm ref="addForm" title="新建" :dialogVisible.sync="addVisible" @save="addSave"></newEditForm>
        <!--编辑-->
        <newEditForm ref="editForm" title="编辑" :dialogVisible.sync="editVisible" :editData="editData"
                     @save="editSave"></newEditForm>

    </div>
</template>

<script>
    import newEditForm from '../components/formDialog7-2'

    export default {
        name: "formDemo7-2",
        data() {
            return {
                addVisible: false,
                editVisible: false,
                editData: {}
            }
        },
        components: {
            newEditForm
        },
        methods: {
            addItem() {
                this.addVisible = true;
                this.$nextTick(() => {
                    this.$refs.addForm.resetForm();
                })
            },
            editItem() {
                this.editVisible = true;
                this.editData = {
                    name: '张三',
                    file: [{name: "11.txt"}]
                }
                this.$nextTick(() => {
                    this.$refs.editForm.resetForm();
                })

            },
            addSave(data) {
                console.log(data);
            },
            editSave(data) {
                console.log(data);

            }
        }
    }
</script>

<style lang="less" scoped>
    .formDemo-page {
        text-align: left;
    }
</style>

子组件:

<template>
    <div class="formDialog7-2">
        <!--功能(多个文件):1、上传文件校验 2、随表单一块提交 3、文件列表展示 4、列表删除后文件联动
        5、支持多个文件上传且分别校验 6、去掉列表展示的动画效果-->
        <el-dialog
                :title="title"
                :visible="dialogVisible"
                :close-on-click-modal="false"
                :close-on-press-escape="false"
                @update:visible="changeVisible()"
                width="30%">
            <el-form ref="form" :model="form" label-width="80px" :rules="rules">
                <el-form-item label="名称" prop="name">
                    <el-input v-model="form.name"></el-input>
                </el-form-item>
                <el-form-item label="上传文件" class="is-required" prop="file">
                    <el-upload
                            class="upload-demo"
                            drag
                            action=""
                            accept=".txt,.jpg"
                            :on-change="handleChange"
                            :auto-upload="false"
                            :file-list="form.file"
                            :on-remove="handleAddRemove"
                            multiple
                    >
                        <i class="el-icon-upload"></i>
                        <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
                        <div class="el-upload__tip" slot="tip">只能上传txt/jpg文件,且不超过5kb</div>
                    </el-upload>
                    <!--文件校验提示信息,在添加el-form-item中class="is-required"-->
                    <div class="file-error" v-show="errFileMsg">{{errFileMsg}}</div>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
            <el-button @click="changeVisible()">取 消</el-button>
            <el-button type="primary" @click="save()">确 定</el-button>
        </span>
        </el-dialog>
    </div>
</template>

<script>
    export default {
        name: "formDialog7-2",
        props: ['dialogVisible', 'title', 'editData'],
        data() {
            return {
                form: {
                    name: '',
                    file: []
                },
                rules: {
                    name: [{required: true, message: '请输入名称', trigger: 'blur'}],
                },
                errFileMsg: ''

            }
        },
        watch: {
            editData(value) {
                this.form = {...value}
            }
        },
        methods: {
            resetForm() {
                this.$refs.form.resetFields();
                this.errFileMsg = '';
            },
            // 取消
            changeVisible(value = false) {
                this.$emit('update:dialogVisible', value)
            },
            // 改变文件
            handleChange(file, fileList) {
                // 个人理解:this.form.file是已有列表,fileList是已有列表加上新加的文件,需手动赋值处理;
                // 如果不处理,已有列表会自动显示fileList(检测到this.form.file变化就显示this.form.file,否则显示fileList)
                //场景一:用message提示信息最方便
                console.log(fileList);
                if (this.validateFile(file)) {
                    //校验通过
                    this.form.file.push(file);
                } else {
                    //手动更新
                    this.form.file.splice();
                }

                //场景二:如果非要在错误信息出显示提醒
                // let flag = true;
                // this.form.file = [];
                // for (let file of fileList) {
                //     if (this.validateFile(file)) {
                //         //校验通过
                //         this.form.file.push(file);
                //     } else {
                //         //手动更新
                //         this.form.file.splice();
                //         flag = false;
                //     }
                // }
                // if (flag) {
                //     this.errFileMsg = ''
                // }
            },
            //移除文件
            handleAddRemove(file, fileList) {
                this.form.file = fileList;
            },
            save() {
                const fileLength = this.form.file.length;
                this.errFileMsg = fileLength === 0 ? '请上传文件' : '';
                if (!this.validate() || fileLength === 0) return;
                this.$emit('save', this.form)
            },
            // 文件校验
            validateFile(file) {
                //场景一:用提示信息最方便,场景二注释
                this.errFileMsg = '';
                if (!file) {
                    //场景一:用提示信息最方便
                    this.$message.error('请上传文件')
                    // 场景二:如果非要在错误信息出显示提醒
                    // this.errFileMsg = '请上传文件';
                    return false;
                }
                //file格式及大小校验
                const validName = file.name.endsWith('.txt') || file.name.endsWith('.jpg');
                const validSize = file.size < (1024 * 5);
                if (!validName) {
                    //场景一:用提示信息最方便
                    this.$message.error('文件类型不正确')
                    // 场景二:如果非要在错误信息出显示提醒
                    // this.errFileMsg = '文件类型不正确';
                    return false;
                } else if (!validSize) {
                    //场景一:用提示信息最方便
                    this.$message.error('文件大小超出限制')
                    // 场景二:如果非要在错误信息出显示提醒
                    // this.errFileMsg = '文件大小超出限制';
                    return false;
                } else {
                    return true;
                }
            },
            validate() {
                let result = false;
                this.$refs.form.validate((valid) => {
                    result = valid;
                })
                return result;
            }
        }
    }
</script>

<style lang="less" scoped>
    .formDialog7-2 {
        .file-error {
            color: #F56C6C;
            font-size: 12px;
            line-height: 1;
            padding-top: 4px;
            position: absolute;
            top: 100%;
            left: 0;
        }

        //场景:去掉列表展示的动画效果
        /deep/ .el-list-enter-active,
        /deep/ .el-list-leave-active {
            transition: none;
        }
    }
</style>