Bootstrap

vue+elementUI,实现表单验证中的图片上传验证(el-form与el-upload)

简介

目前在做一个商城后台管理系统,在实现表单的过程中需要上传商品图片、二维码、头像等,需求是每次只能上传一张图片,并且需要进行相关的非空验证,操作演示如下图所示:
在这里插入图片描述
以下是具体的实现思路,希望能帮到大家。

el-form表单的实现及非空验证

本文所实现的表单验证是普通的输入验证,若想自定义表单验证规则,可以前往elementUI官方文档进行学习。
表单验证可以理解为以下几个步骤:
1、在 el-form 上添加规则对象,名称可自定义 :rules=“kfFormRules”
2、给 el-form-item 添加属性 props=“名称”,需注意的是这个名称需要与规则对象kfFormRules中的属性名一致,不然验证不了
3、在 data 中定义 kfFormRules规则。
4、表单的清空,需要给表单绑定一个ref,js中通过$ r e f s refs refs我们可以获取到整个表单对象。然后通过resetFields()方法我们可以清空整个表单,例如:this. r e f s refs refs.kfFormRef.resetFields();。通过clearValidate()我们可以移除某一个验证规则的提示,例如:this.$refs.kfFormRef.clearValidate(‘codeImg’); (注:CSDN文章编写有些地方写不上美元符号,若要复制代码请直接前往代码区。)
5、关于图片的重置,见下方的el-upload部分
页面布局如下:
在这里插入图片描述
页面布局代码如下:

<template>
    <!-- 商品详情界面 -->
    <div>
        <!-- 面包屑导航区域 -->
        <breadcrumb></breadcrumb>
        
        <!-- 卡片视图区域 -->
        <el-card>
            <div slot="header">
                <span>基本信息</span>
            </div>
            <el-form label-width="120px" :model="kfForm" ref="kfFormRef" :rules="kfFormRules">
                <el-form-item label-width="0px" prop="name">
                    <el-input placeholder="客服名称" v-model="kfForm.name">
                        <template slot="prepend">客服名称</template>
                    </el-input>
                </el-form-item>
                <el-form-item label-width="0px" prop="wx_number">
                    <el-input placeholder="微信号" v-model="kfForm.wx_number">
                        <template slot="prepend">微信号码</template>
                    </el-input>
                </el-form-item>
                <el-form-item label="客服头像上传:" prop="headImg">
                    <el-upload
                        :action="uploadURL"
                        list-type="picture-card"
                        :class="{hide:hideUpload}"
                        name="files"
                        :on-preview="handlePreview"
                        :on-remove="remove"
                        :on-change="uploadChange"
                        :http-request="headUpload">
                        <i class="el-icon-plus"></i>
                    </el-upload>
                    <el-dialog :visible.sync="previewVisible">
                        <img width="100%" :src="previewPath" alt="">
                    </el-dialog>
                </el-form-item>
                 <el-form-item label="微信二维码上传:" prop="codeImg">
                    <el-upload
                        :action="uploadURL"
                        list-type="picture-card"
                        :class="{hide:hideCode}"
                        name="files"
                        :on-preview="codePreview"
                        :on-remove="codeRemove"
                        :on-change="codeChange"
                        :http-request="codeUpload">
                        <i class="el-icon-plus"></i>
                    </el-upload>
                    <el-dialog :visible.sync="codeVisible">
                        <img width="100%" :src="codePath" alt="">
                    </el-dialog>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" @click="certain">确 定</el-button>
                    <el-button type="primary" @click="clearAll">重 置</el-button>
                </el-form-item>
            </el-form>
        </el-card>
    </div>
</template>

el-upload,只允许上传一张图片的实现步骤

el-upload内置有on-remove和on-change等函数勾子,限制只传一张图,主要也是在这两个勾子中去操作
(1)on-remove:文件列表移除文件时的钩子
(2)on-change:文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用
el-upload:上传一张图片后隐藏上传按钮的具体步骤如下:
(1)el-upload里面绑定一个占位class,:class="{hide:hideUpload}"
(2)data里面初始值:hideUpload: false, limitCount:1
(3)on-change绑定的方法里写:this.hideUpload = fileList.length >= this.limitCount;
(4)on-change绑定的方法里写:this.hideUpload = fileList.length >= this.limitCount;
(5)style,把scoped去掉(或者外部引入样式文件,主要目的是为了修改element-ui自带的样式)

<style>
	.hide .el-upload--picture-card {
	  display: none;
	}
</style>

关于图片的重置,我用了一个比较笨的方法,具体可以看下面我的实现步骤:
(1)我定义了两个全局参数headFile和headFileList
(2)在on-change的uploadChange方法中给headFile,headFileList赋值
(3)在重置按钮的clearAll()方法中,判断headFileList的数组长度是否大于0,因为已经做了限制这个数组的长度不是0就是1,当它大于0的时候,移除数组中的值,然后将他作为第二个参数传入**remove()**方法中,小伙伴们肯定有疑问了,为什么不直接传一个空数组,更简单更方便,经测试如果直接传一个空数组,无法移除图片,所以采取了先获取再删除的方式。
代码片段如下:

data() {
        return {
            uploadURL: '',
            previewPath: '',
            previewVisible: false,
            hideUpload: false,
            limitCount: 1,
          	headFile: '',
            headFileList: '',
        }
    },
 // 处理图片预览效果
        handlePreview(file) {
            this.previewPath = file.url;
            this.previewVisible = true
        },
        remove(file, fileList) {
            if(fileList.length==0){
                this.kfFormRules.headImg = [{ required: true, message: '请上传微信头像', trigger: 'change'}];
            }
            this.hideUpload = fileList.length >= this.limitCount;
        },
        uploadChange(file, fileList) {
            this.headFile = file;
            this.headFileList = fileList;
            if(fileList.length==1) {
                let {headImg, ...data} = this.kfFormRules; //删除kfFormRules中的headImg属性
                this.kfFormRules = data;
            }
            this.$refs.kfFormRef.clearValidate('headImg');
            this.hideUpload = fileList.length >= this.limitCount;
        },
        clearAll() {
            this.$refs.kfFormRef.resetFields();
            if(this.headFileList.length>0) {
                this.headFileList.splice(0,1)
                this.remove(this.headFile,this.headFileList);
            }
            if(this.codeFileList.length>0) {
                this.codeFileList.splice(0,1)
                this.codeRemove(this.codeFile,this.codeFileList)
            }
        },

el-form中,实现el-upload的验证

在这里插入图片描述点击确定按钮,触发验证规则。
在这里插入图片描述点击图片上传,清空验证结果,并且修改验证对象kfFormRules,移除里面关于头像上传的条件headImg,这些逻辑需要在on-change中去实现,然后在点击确定就不会有关于headImg的验证,具体可以看上图标出的控制台提示。
代码实现如下:

codeChange(file, fileList) {
            this.codeFile = file;
            this.codeFileList = fileList;
            if(fileList.length==1) {
                let {codeImg, ...data} = this.kfFormRules;
                this.kfFormRules = data;
            }
            this.$refs.kfFormRef.clearValidate('codeImg');
            this.hideCode = fileList.length >= this.limitCode;
        },

在点击删除图片时,需要把验证规则重新加回来,代码实现如下:

 codeRemove(file, fileList) {
            if(fileList.length==0){
                this.kfFormRules.codeImg = [{ required: true, message: '请上传微信二维码', trigger: 'change'}];
            }
            this.hideCode = fileList.length >= this.limitCode;
        },

全部代码如下:

<template>
    <!-- 商品详情界面 -->
    <div>
        <!-- 面包屑导航区域 -->
        <breadcrumb></breadcrumb>
        
        <!-- 卡片视图区域 -->
        <el-card>
            <div slot="header">
                <span>基本信息</span>
            </div>
            <el-form label-width="120px" :model="kfForm" ref="kfFormRef" :rules="kfFormRules">
                <el-form-item label-width="0px" prop="name">
                    <el-input placeholder="客服名称" v-model="kfForm.name">
                        <template slot="prepend">客服名称</template>
                    </el-input>
                </el-form-item>
                <el-form-item label-width="0px" prop="wx_number">
                    <el-input placeholder="微信号" v-model="kfForm.wx_number">
                        <template slot="prepend">微信号码</template>
                    </el-input>
                </el-form-item>
                <el-form-item label="客服头像上传:" prop="headImg">
                    <el-upload
                        :action="uploadURL"
                        list-type="picture-card"
                        :class="{hide:hideUpload}"
                        name="files"
                        :on-preview="handlePreview"
                        :on-remove="remove"
                        :on-change="uploadChange"
                        :http-request="headUpload">
                        <i class="el-icon-plus"></i>
                    </el-upload>
                    <el-dialog :visible.sync="previewVisible">
                        <img width="100%" :src="previewPath" alt="">
                    </el-dialog>
                </el-form-item>
                 <el-form-item label="微信二维码上传:" prop="codeImg">
                    <el-upload
                        :action="uploadURL"
                        list-type="picture-card"
                        :class="{hide:hideCode}"
                        name="files"
                        :on-preview="codePreview"
                        :on-remove="codeRemove"
                        :on-change="codeChange"
                        :http-request="codeUpload">
                        <i class="el-icon-plus"></i>
                    </el-upload>
                    <el-dialog :visible.sync="codeVisible">
                        <img width="100%" :src="codePath" alt="">
                    </el-dialog>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" @click="certain">确 定</el-button>
                    <el-button type="primary" @click="clearAll">重 置</el-button>
                </el-form-item>
            </el-form>
        </el-card>
    </div>
</template>

<script>
import axios from 'axios' 
import breadcrumb from "../../components/breadcrumb/breadcrumb";
export default {
    components: {
        breadcrumb,
    },
    data() {
        return {
            // 上传图片的URL地址
            uploadURL: '',
            previewPath: '',
            previewVisible: false,
            codePath: '',
            codeVisible: false,
            hideUpload: false,
            hideCode: false,
            limitCount: 1,
            limitCode: 1,
            headImg: [],//头像
            wxImg: [],//微信二维码
            kfForm: {
                name: '',
                wx_number: '',
            }, //分佣弹框的表单对象
            // 表单校验规则
            kfFormRules: {
                name: [
                    { required: true, message: '请输入客户专员名称', trigger: 'blur' },
                ],
                wx_number: [
                    { required: true, message: '请输入客服专员微信号', trigger: 'blur' },
                ],
                headImg: [{ required: true, message: '请上传客服头像', trigger: 'change'}],
                codeImg: [{ required: true, message: '请上传微信二维码', trigger: 'change'}],
            },
            headFile: '',
            headFileList: '',
            codeFile: '',
            codeFileList: '',
        }
    },
    methods: {
        headUpload(params) {
            let param = new FormData();
            param.append("files", params.file);
            axios({
                url: this.adminConfig.uploadPath+"upload/upload/",
                method: "post",
                data: param,
                headers: {
                    "Content-Type": "multipart/form-data"
                }
            }).then(res => {
                this.headImg = [];
                this.headImg.push(res.data.data)
            })
        },
        codeUpload(params) {
            let param = new FormData();
            param.append("files", params.file);
            axios({
                url: this.adminConfig.uploadPath+"upload/upload/",
                method: "post",
                data: param,
                headers: {
                    "Content-Type": "multipart/form-data"
                }
            }).then(res => {
                this.wxImg = [];
                this.wxImg.push(res.data.data)
            })
        },
        // 处理图片预览效果
        handlePreview(file) {
            this.previewPath = file.url;
            this.previewVisible = true
        },
        remove(file, fileList) {
            if(fileList.length==0){
                this.kfFormRules.headImg = [{ required: true, message: '请上传微信头像', trigger: 'change'}];
            }
            this.hideUpload = fileList.length >= this.limitCount;
        },
        uploadChange(file, fileList) {
            this.headFile = file;
            this.headFileList = fileList;
            if(fileList.length==1) {
                let {headImg, ...data} = this.kfFormRules;
                this.kfFormRules = data;
            }
            this.$refs.kfFormRef.clearValidate('headImg');
            this.hideUpload = fileList.length >= this.limitCount;
        },
        // 处理图片预览效果
        codePreview(file) {
            this.codePath = file.url;
            this.codeVisible = true
        },
        codeRemove(file, fileList) {
            if(fileList.length==0){
                this.kfFormRules.codeImg = [{ required: true, message: '请上传微信二维码', trigger: 'change'}];
            }
            this.hideCode = fileList.length >= this.limitCode;
        },
        codeChange(file, fileList) {
            this.codeFile = file;
            this.codeFileList = fileList;
            if(fileList.length==1) {
                let {codeImg, ...data} = this.kfFormRules;
                this.kfFormRules = data;
            }
            this.$refs.kfFormRef.clearValidate('codeImg');
            this.hideCode = fileList.length >= this.limitCode;
        },
        certain() {
            console.log("dd",this.kfFormRules)
            this.$refs.kfFormRef.validate((valid) => {
            if (valid) {
                alert('submit!');
            } else {
                console.log('error submit!!');
                return false;
            }
            });
        },
        clearAll() {
            this.$refs.kfFormRef.resetFields();
            if(this.headFileList.length>0) {
                this.headFileList.splice(0,1)
                this.remove(this.headFile,this.headFileList);
            }
            if(this.codeFileList.length>0) {
                this.codeFileList.splice(0,1)
                this.codeRemove(this.codeFile,this.codeFileList)
            }
        },
       
    }, 
    mounted() {
        
    }
}
</script>

<style lang="less" scoped>
    .writeBox {
        display: flex;
        justify-content: space-between;
        flex-direction: row;
        flex-wrap: wrap;
        width: 100%;
        margin-bottom: 20px;
    }
    .el-row {
        width: 30%;
        margin-right: 10px;
        margin-bottom: 8px;
    }
    .el-col {
        white-space: nowrap;
    }
    .el-form-item {
        .el-input {
            width:400px;
            margin-right: 10px;
        }
    }
</style>
;