我重生了 校霸抽。。。咳咳错了。。。我重生了 使用vue3实现制作验证表格、
老规矩 先上图(最后附带源码)
看起来简单就是单纯的form套table,nonono里面有门道的,且听我娓娓道来
(那个。。。刚重生代码水平不太行,目前封装的只是实现了功能,但是感觉还有优化的空间,不知道咋优化,大佬们给点意见,球球你们了 /流泪)
首 先 4 个 问 题
1、form怎么写
2、值,以及验证的值怎么绑定
3、必填的时候表头展示
4、不同组件库怎么切换
5、新增和删除和验证数据
6、源码以及,组件化使用
1、form怎么写
table单元格内容的校验可以通过插槽的写法进行form的插入
普通的input样式就是这样的可以实现验证
2、值,以及验证的值怎么绑定
通过设置 :prop=" ‘tableData.’ + scope.$index + ‘.tel’ "可以实现校验值的绑定
tableDtata要放在form里面嗷
3、必填的时候表头展示
表头的展示 是通过:header-cell-class-name=‘addHeaderCellClassName’ 添加指定类名来实现带红点的效果
_props.requird为父组件传进来的需要验证的表头
<script>
function addHeaderCellClassName({ row, column, rowIndex, columnIndex }) {
//_props.requird为父组件传进来的需要验证的表头 格式 :['材料名称', '型号', '进场数量']
if (_props.required.includes(column.label)) {
return 'requiredClass'
}
}
</script>
<style lang="scss" scoped>
:deep(.requiredClass .cell::before) {
content: "*";
color: #f56c6c;
margin-right: 4px;
}
</style>
4、不同组件库怎么切换
通过vue的内置组件component和slot实现标签的动态切换
5、新增和删除数据
// 新增数据
function onAddTableLine(value) {
form.value.tableData.push(value||{});
}
// 删除数据
function onRemoveTableLine() {
form.value.tableData = form.value.tableData.filter(
(item) => !multipleSelection.value.some((i) => i == item)
);
}
// 验证表单
const valiDate = (call) => {
_FormRef.value.validate((valid, fields) => {
console.log(valid, fields)
})
};
6、源码以及,组件化使用
<template>
<div>
<!-- 调试使用 -->
<!-- <el-button type="primary" @click="valiDate">校验规则</el-button>
<el-button type="primary" @click="onAddTableLine">新增</el-button>
<el-button type="warning" @click="onRemoveTableLine">删除</el-button> -->
<el-form ref="_FormRef" :model="form">
<el-table :data="form.tableData" border style="width: 100%; margin-top: 20px" row-key="id"
:header-cell-class-name='addHeaderCellClassName' ref="tableRef" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column v-for="(option, index) in options" :key="index" :label="option.label">
<template v-if="option.npFormSlot" #default="scope">
<slot :name="option.npFormSlot" :row="scope" />
</template>
<template v-else #default="scope">
<el-form-item :prop="'tableData.' + scope.$index + '.' + option.prop" :rules="rules[option.prop]">
<slot :name="'default'" :item="{ option, tableData, changeDataHandler }">
<el-date-picker v-if="option.tag == 'date-picker'" v-model="scope.row[option.prop]"
:type="option.pickerType || 'date'" :format="option.format || 'YYYY/MM/DD'"
:value-format="option.format || 'YYYY-MM-DD'" :disabled="option.disabled" />
<component v-else :is="`el-${option.tag}`" :type="option.type || 'txt'" v-model="scope.row[option.prop]"
:disabled="option.disabled">
<template v-if="option.options">
<el-radio v-if="option.tag == 'radio-group'" v-for="i in option.options" :key="i.value"
:label="i.value" size="large">{{ i.label }}</el-radio>
<el-option v-else v-for="item in option.options" :key="item.value" :value="item.value"
:label="item.label">
{{ item.label }}
</el-option>
</template>
</component>
<div class="disableBox" v-if="option.disableBox">
{{ scope.row[option.prop] }}
</div>
</slot>
</el-form-item>
</template>
</el-table-column>
</el-table>
</el-form>
</div>
</template>
<script setup>
import { ref, toRefs, watch, defineExpose, shallowRef } from "vue";
const _props = defineProps({
Data: {
type: Object,
default: () => ({})
},
options: {
type: Array,
required: true
},
required: {
type: Array,
default: []
}
})
const _emit = defineEmits(["updateFormData"]);
const multipleSelection = ref([]);
const form = ref({
tableData: _props.Data
})
const tableRef = shallowRef();
const rules = mergeRule(_props.options || []);
watch(
() => form.value.tableData,
() => {
console.log('监听到变化')
_emit("updateFormData", form.value.tableData);
},
{ deep: true }
);
/**
* 改变formData的数据
* @param prop 属性名
* @param value 属性值
*/
function changeDataHandler(prop, value) {
console.log("插槽回调");
// formData.value[prop] = value;
}
const _FormRef = ref();
/**
* 验证表单
* @param call
*/
const validate = (call) => {
return _FormRef.value?.validate(call);
};
/**
* 操作el-form ref提供的方法及属性
* @param call
*/
const doFormRef = (call) => {
call(_FormRef.value);
};
// 清除表单验证
function clearValidate() {
_FormRef.value.clearValidate();
}
defineExpose({
validate,
doFormRef,
clearValidate,
onAddTableLine,
onRemoveTableLine,
form,
});
// 新增数据
function onAddTableLine(value) {
form.value.tableData.push(value||{});
}
// 删除数据
function onRemoveTableLine() {
form.value.tableData = form.value.tableData.filter(
(item) => !multipleSelection.value.some((i) => i == item)
);
}
// 测试-验证表单
const valiDate = (call) => {
_FormRef.value.validate((valid, fields) => {
console.log(valid, fields)
})
};
// 选择表格数据
const handleSelectionChange = (val) => {
multipleSelection.value = val;
};
function addHeaderCellClassName({ row, column, rowIndex, columnIndex }) {
if (_props.required.includes(column.label)) {
return 'requiredClass'
}
}
/**
* 合并formItem 的rules
* @param formItem
*/
function mergeRule(formItem) {
const rules = {}
formItem.forEach(item => {
if (Array.isArray(item.rule) && item.rule?.length > 0) {
rules[item.prop] = item.rule
}
})
return rules
}
</script>
<style lang="scss" scoped>
:deep(.requiredClass .cell::before) {
content: "*";
color: #f56c6c;
margin-right: 4px;
}
</style>
附带插槽写法
option参数参考 (:required上面已经提到过了 这里就不详细说了哈哈哈哈 string[ ]格式嗷~)
:required =“[‘材料名称’, ‘型号’, ‘进场数量’]”
cosnt data = [{
label: '问题类型',
prop: 'issueType',
tag: 'select',
options: [
{ label: '是', value: 1 },
{ label: '否', value: 0 }
],
},
{
label: '问题说明',
prop: 'issueDescription',
tag: 'input',
rule: [
{
required: true,
message: "请输入问题说明",
trigger: "change",
},
],
},
{
label: '问题发现人',
prop: 'required',
disableBox: true
},
{
label: '附件',
prop: 'question',
npFormSlot: 'button'
},]
父组件中的调用
// formTable新增数据
const onAddTableLine = () => {
_formTableChild.value.onAddTableLine()
}
// formTable删除数据
const onRemoveTableLine = () => {
_formTableChild.value.onRemoveTableLine()
}
// 子组件回调
const upDataFormTable = (val) => {
console.log(val)
formData.value.createXMProjectPatrolCheckItemList = val
}
// 父组件进行表单验证
const _formTableChildVerify = async () => {
return await _formTableChild.value.validate((valid) => {
console.log(valid);
});
};
有这种需求可以这样传参~
// formTable新增数据
const onAddTableLine = () => {
_formTable.value.onAddTableLine({ required: '张三' })
}
哎呀,体力不支了,今天的代码就先到这里吧,明天依然是光芒万丈