业务需求描述

界面展示:
本次组盘数为用户需要填写的表单项
同样格式的表单项会有多个用户每次在【物资扫码】成功后,都会在右侧【物资列表】中增加一个如图的结构(分为上中下三部分,上为【物资编号】,中为表格展示的物资基本信息,下为用户需要填写的表单项【本次组盘数】),需要在用户点击【保存】时,校验每一个表单项必填且数量大于1。

所用技术描述

客户要求该界面支持双端(网页端 + 移动设备端)
网页端采用:vue+elementui
移动设备端采用:uniapp+uview

网页端(vue+elementui)实现方式及具体代码

界面左侧就是简单的点击事件不做赘述,重点讲右侧的表单校验。

<el-col :span="18">
    <div class="main_div">
        <div class="table_item" v-for="(item,index) in tableData" :key="index">
            <div class="materials_div">
                <div class="materials_code">{{index + 1}} | 批次号:{{item.batchNum}}</div>
            </div>
            <div class="table_div">
                <div style="width:91%">
                		<!-- el-table组件接收一个数组,而tableData是一个对象数组,所以此处将遍历得到得对象转变为一个数组赋值给组件 -->
                		<!-- 此处可以写[tableData[index]] 也可以写 [item],效果是一样的 -->
                    	<el-table 
	                         v-loading="loading" 
	                         :data="[tableData[index]]" 
	                         border 
	                         highlight-current-row
	                     >
                         <el-table-column label="物资类别" align="center" prop="materialsTypeName" />
                         <el-table-column label="物资名称" align="center" prop="materialsName" />
                         <el-table-column label="规格" align="center" prop="specs" />
                         <el-table-column label="数量" align="center" prop="repertoryNum" />
                         <el-table-column label="待组盘数量" align="center" prop="discNum" />
                         <el-table-column label="所属仓库" align="center" prop="storeId" :formatter="storeIdFormat" />
                         <el-table-column label="所属库区" align="center" prop="reserveId" :formatter="reserveIdFormat" />
                         <el-table-column label="备注" align="center" prop="remark" />
                     </el-table>
                </div>
                <div class="delte_btn" @click="deleteHandle(item,index)">删除</div>
            </div>
            <!-- el-form表单接收一个数组,即遍历得到的tableData[index] -->
            <!-- 表单校验规则比较简单,我选择了写在行内的形式 -->
            <el-form class="form" ref="materialsManageForm" :model="tableData[index]">
               <el-form-item label="本次组盘数" prop="thisNum"
                   :rules="{
                       required: true, message: '本次组盘数不能为空', trigger: 'blur'
                   }"
               >
                   <el-input-number 
                       v-model="tableData[index].thisNum"
                       :min="1"
                   >
                   </el-input-number>
               </el-form-item>
           </el-form>
        </div>
    </div>
    <div class="save_btn" @click="submitForm">保存</div>
</el-col>
export default {
    data() {
        return {
            // 组盘数据,是一个对象数组,数据通过用户扫码得到的编号访问后台得到,大致就是=>[{},{}]
            tableData:[],
        };
    },
    methods:{
		// 保存
        submitForm() {
       		//flag为表单校验是否成功的标志变量
            var flag = true;
            //当一个页面有多个refs 为 materialsManageForm 的表单时,
            //this.$refs["materialsManageForm"]会得到一个数组,于是遍历这个数组,去校验每一个表单是否符合校验规则
            this.$refs["materialsManageForm"].forEach(ii=>{
                ii.validate((valid) => {
                    if (valid) {
                        //校验成功,不对flag做操作
                    } else {
                    		//一旦有一个表单不符合校验规则,将flag设置为false
                        flag = false;
                        console.log('error submit!!');
                        return false;
                    }
                });
            })
            if(flag){
                //校验成功,访问后台做保存数据等操作
            }else{
                //校验失败,此时界面上已经会有elemnt自带的提示
                //可不做操作,也可提示用户,也可做后续操作
            }
        }
	}
}

移动端(uniapp+uview)实现方式及具体代码

同样只讲右侧的表单校验。

<view class="right_view">
	<view class="main_div">
		<view class="table_item" v-for="(item,index) in tableData" :key="index">
			<view class="materials_div">
				<view class="materials_code">{{index + 1}} | 物资编号:{{item.materialsCode}}</view>
			</view>
			<view class="table_div">
				<view style="width:91%">
					<!-- 此处的表格并非uview中自带的组件,需要从uniapp插件市场导入项目 -->
					<!-- uniapp官网相关介绍 => https://uniapp.dcloud.net.cn/component/uniui/uni-table.html#%E4%BB%8B%E7%BB%8D -->
					<!-- uni-table组件地址 =>  https://ext.dcloud.net.cn/plugin?name=uni-table -->
					<uni-table border stripe emptyText="暂无更多数据">
						<!-- 表头行 -->
						<uni-tr>
							<uni-th align="center">物资类别</uni-th>
							<uni-th align="center">物资名称</uni-th>
							<uni-th align="center">规格</uni-th>
							<uni-th align="center">数量</uni-th>
							<uni-th align="center">待组盘数量</uni-th>
							<uni-th align="center">所属仓库</uni-th>
							<uni-th align="center">所属库区</uni-th>
							<uni-th align="center">备注</uni-th>
						</uni-tr>
						<!-- 表格数据行 -->
						<uni-tr v-for="(ite, ind) in [item]" :key="ind">
							<uni-td align="center">{{ite.materialsTypeName}}</uni-td>
							<uni-td align="center">{{ite.materialsName}}</uni-td>
							<uni-td align="center">{{ite.specs}}</uni-td>
							<uni-td align="center">{{ite.repertoryNum}}</uni-td>
							<uni-td align="center">{{ite.discNum}}</uni-td>
							<uni-td align="center">{{storeIdFormat(ite)}}</uni-td>
							<uni-td align="center">{{reserveIdFormat(ite)}}</uni-td>
							<uni-td align="center">{{ite.remark}}</uni-td>
						</uni-tr>
					</uni-table>
				</view>
				<view class="delte_btn" @click="deleteHandle(item,index)">删除</view>
			</view>
			<u--form errorType="toast" ref="materialsManageForm" :model="tableData[index]"
				labelWidth="auto">
				<u-form-item label="本次组盘数" prop="thisNum">
					<u-number-box v-model="tableData[index].thisNum" integer :min="1"
						></u-number-box>
				</u-form-item>
			</u--form>
		</view>
	</view>
	<view class="save_btn" @click="submitForm">保存</view>
</view>
export default {
    data() {
        return {
            // 组盘数据,是一个对象数组,数据通过用户扫码得到的编号访问后台得到,大致就是=>[{},{}]
            tableData:[],
            //表单项校验是否成功的标志属性,因为uview用了promise方式进行校验,所以此处得把formFlag定义在这里
            formFlag:true
        };
    },
    methods:{
    	//此处为用户扫码后向右侧新增一个物料的方法,uniapp和element不同,uniapp需要手动给表单添加校验规则,故此把这个方法写出来,
    	//访问后台过程有所简略,重点是向tableData push一个新的对象时,对象中必须有要校验的表单项属性,
    	//该例子中为【thisNum】。如果没有该属性,控制台会报错
    	newRow() {
			var _this = this;
			this.tableData.push({
				thisNum: 0
			});
			//给materialsManageForm添加规则时,节点必须已经挂载完毕,所以用了setTimeout。目前没想到更好的办法,等以后想到了再回来补充
			setTimeout(() => {
				_this.$refs["materialsManageForm"].forEach(ii => {
					ii.setRules(_this.formRules)
				})
			}, 1000)
		},
		//uview采用了promise方式对表单进行校验,所以就不能再使用简单的forEach,因为我们需要等待所有的表单都校验完毕,再去获取flag
		//此处为达到这个效果,用了new Promise的办法
		checkFormValid() {
			this.formFlag = true;
			return new Promise((resolve, reject) => {
				let list = [];
				this.$refs["materialsManageForm"].forEach(ii => {
					const p = new Promise((reso, rej) => {
						ii.validate().then(res => {
							// 校验通过,this.formFlag值不变
						}).catch(errors => {
							// 有校验不通过的,this.formFlag值为false
							this.formFlag = false;
						}).finally(() => {
							reso(); //单个接口执行完毕
						})
					})
					list.push(p)
				})
				Promise.all(list).then(result => {
					resolve() //所有接口都执行完毕
				})
			})
		},
		// 保存
		submitForm() {
			var _this = this;
			this.checkFormValid().then(res => {
				if (_this.formFlag) {
					//表单校验成功,访问后台做保存数据等操作
				}
			})
		}}
}

以上就是两种框架校验的具体过程了,此博文重点在分享完成需求的方法和思路,所以如果因为省略了很多中间代码,在复制过程中有所遗漏导致代码不能粘贴即用,还望读者见谅。

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

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

更多推荐