需求描述:table中有多个需要编辑的字段,并且需要校验空值或非正数
1.方案
一. 手搓el-input + div
仿照el-form校验提示,用el-input和div写样式,满足需求。
问题:列表数据量大,不好控制提示显示隐藏。保存时校验值需要遍历列表挨个字段判空
二. el-form + el-input
把form和input封装到一个组件中,列表上每一个input,其实是form + input
2.组件代码
// 子组件核心
validChange(val) {
let isValid = null; // 父级使用判断该form是否通过表单校验
this.isFocus = false
// 个人业务需求 start (可删除)
// 保留两位小数显示
if (parseFloat(val).toString() !== 'NaN') {
this.value = parseFloat(val).toFixed(2)
}
// 个人业务需求 end
// 给form赋值
this.form[this.propValue] = this.value;
this.$refs["formRef"].validate(valid => {
if (valid) {
isValid = true
this.$emit("updateData", this.value);
} else {
isValid = false
}
});
return isValid
}
3. 父组件调用
// 自己和子组件对应一下传参
<el-table-column label="采购单价" align="left" width="120" prop="bugSinPrice">
<template slot-scope="scope">
<valid-input
:ref="`bugSinPriceRef${scope.$index}`"
:labelValue="'采购单价'"
propValue="bugSinPrice"
:indexValue="scope.$index"
:unit="'元'"
@updateData="val => scope.row.bugSinPrice = val"
/>
</template>
</el-table-column>
// 提交信息
handleSubmit() {
let refList = this.$refs
Object.keys(refList).forEach(key => {
if (this.$refs[[key]] && this.$refs[[key]].validChange) {
// 如果 this.$refs[[key]].validChange() 有一个为false
// 说明有数据没填禁止提交
// 后续逻辑...
}
})
}
4.通用性处理(续)
第一版:只处理了input组件并且没有回显初始化的数据
第二版:新增了el-date-picker 和 el-select组件
组件变动
/**
*这部分是props的修改
*传参增加了 initValue 渲染的初始值
*传参增加了 select* 相关参数
*/
// 默认值
initValue: {
type: String,
default: () => {
return ''
}
},
// 选择框传参 start
selectOptions: {
type: Array,
default: () => {
return []
}
},
selectLabel: {
type: String,
default: () => {
return 'value'
}
},
selectKey: {
type: String,
default: () => {
return 'value'
}
}
// 选择框传参 end
/**
*form表单校验修改
*根据需要显示的组件自定义校验规则
*因为是通用型组件,校验规则没有涉及太多业务需求
*/
let formCheck = (rule, value, callback) => {
switch (this.itemType) {
// 输入框组件校验
case 'input':
const reg1 = /^(-)?[0-9]+([.][0-9]{1,})?$/
const reg2 = /^-[0-9]+([.][0-9]{1,})?$/
if (!value) {
callback(new Error(`${this.labelValue}不能为空`))
} else {
// 判断是否为数字
if (reg1.test(value)) {
// 判断是否为正数
if (reg2.test(value)) {
callback(new Error('不能输入负数'))
} else {
callback()
}
} else {
callback(new Error('只能输入数字'))
}
}
break;
// 选择框组件校验
case 'select':
if (!value) {
callback(new Error(`${this.labelValue}不能为空`))
} else {
callback()
}
break;
// 日期组件校验
case 'date':
if (!value) {
callback(new Error(`${this.labelValue}不能为空`))
} else {
callback()
}
}
}
created() {
// $set设置值,保证参数为响应式
this.$set(this.form, this.propValue, this.initValue);
// 新增:设置传入的值当做默认值
this.value = this.initValue
},
// 失去焦点更新
validChange(val) {
this.isFocus = false
let isValid = null; // 父级使用判断该form是否通过表单校验
// 修改 start
// 根据显示组件类型,在数据更新时做数据处理(根据自己的业务需求来)
if (this.itemType === 'input') {
// 保留两位小数显示
if (parseFloat(val).toString() !== 'NaN') {
this.value = parseFloat(val).toFixed(2)
}
}
// 修改 end
// 给form赋值
this.form[this.propValue] = this.value;
this.$refs["formRef"].validate(valid => {
if (valid) {
isValid = true
this.$emit("updateData", this.value);
} else {
isValid = false
}
});
return isValid
}
调用变动
/**
* 新增
* itemType 显示的组件类型
* init-value 渲染的默认值
* select组件需要额外传参
* 1.select-options select列表数据
* 2.select-key 根据列表数据自定义 key 字段名
* 3.select-label 根据列表数据自定义 label 字段名
*/
<template slot-scope="scope">
<table-item-valid
:ref="`preDate${scope.$index}`"
itemType="date"
:labelValue="'预计交货日期'"
propValue="preDate"
:indexValue="scope.$index"
:init-value="scope.row.preDate"
@updateData="val => scope.row.preDate = val"
/>
</template>