基于element-plus定义表格行内编辑配置化
- 创业
- 2025-08-13 09:45:01

文章目录 前言一、新增table组件二、使用步骤
前言
在 基于element-plus定义表单配置化 基础上,封装个Element-plus的table表格 由于表格不同于form组件,需自定义校验器,以下组件配置了单个校验,及提交统一校验方法,且自定义必填校验*显示和校验错误部分边框标红等,实际可根据业务及不同场景优化改造相关定义
后期抽空新增表格行及删除行等功能,
一、新增table组件 table-configuration/index.vue <template> <el-table border ref="tableRef" :show-header="showHeader" :data="tableData" style="width: 100%" tooltip-effect :max-height="tablemaxHeight" > <el-table-column type="selection" :fixed="selectionFixed" width="55" v-if="hasSelection"/> <template v-for="(item, index) in tableProperty" :key="item"> <el-table-column :align="align" :sortable="item.sortable" :min-width="item.width" :show-overflow-tooltip="showOverflowTooltip" :label="item.label" > <template #header> <div :class="[getTableHeader(item.property.rules)]" v-html="item.label"></div> </template> <template #default="scope"> <component :class="[scope.$index >=0 && getIsErrorClass(scope.$index, index)]" v-model:content="scope.row[item.field]" v-model="scope.row[item.field]" :property="{...item.property, name: item.field}" :is="item.type" @fieldBlur="(val) => blur(val, item, scope.$index, index)" @fieldChange="(val) => change(val, item, scope.$index, index)" /> </template> </el-table-column> </template> </el-table> </template> <script lang="ts" src="./index.ts"/> <style lang="less"> .is-error .el-select-v2__wrapper,.is-error .el-select-v2__wrapper:focus,.is-error .el-textarea__inner,.is-error .el-textarea__inner:focus { box-shadow: 0 0 0 1px var(--el-color-danger) inset } .is-error .el-input__wrapper { box-shadow: 0 0 0 1px var(--el-color-danger) inset } .table { &_header:before { content: "*"; color: var(--el-color-danger); margin-right: 4px; } } </style> table-configuration/index.ts import { tableHooks } from "@/composables/table-hooks"; import { computed, defineComponent, reactive, ref } from "vue"; import Input from "@/components/form-configuration/input.vue"; import Select from "@/components/form-configuration/select.vue"; import Vhtml from "@/components/form-configuration/v-html.vue"; import Upload from "@/components/form-configuration/upload.vue"; import Switch from "@/components/form-configuration/switch.vue"; import Radio from "@/components/form-configuration/radio.vue"; import Checkbox from "@/components/form-configuration/checkbox.vue"; import Date from "@/components/form-configuration/date.vue"; import Cascader from "@/components/form-configuration/cascader.vue"; import { isArray } from "lodash-es"; import { ElMessage } from "element-plus"; import type { rulesType } from "@/interface"; const ruleType = { required: false, message: '', trigger: '', validator: (val: any) =>{return val} } const fieldProperty = { label: 'demo', type: 'Input', field: 'demo', width: '120px', err: '', property: { maxlength: 200, rules: [ruleType] } } export default defineComponent({ components: { Input, Select, Vhtml, Upload, Switch, Radio, Checkbox, Date, Cascader, }, props: { align: { type: String, default: 'left', // left / center / right }, showHeader: { type: Boolean, default: true, }, selectionFixed: { type: Boolean, default: false, }, showOverflowTooltip: { type: Boolean, default: true, }, hasSelection: { type: Boolean, default: false, }, property: { type: Object, default() { return [ fieldProperty ]; }, }, data: { type: Object, default() { return {}; }, }, }, setup(props, { emit }) { const { tablemaxHeight } = tableHooks(); const tableRef = ref() const tableData = computed({ get() { return props.data; }, set(val) { emit("update:data", val); }, }); const noType = 'noType' const tableProperty = computed(() => props.property); const blur = (val: any, item: typeof fieldProperty, rowIndex: number, colIndex: number) => { let arr: Array<boolean> = [] if (item.property.rules && isArray(item.property.rules)) { arr = validateForField(item, val, 'blur', rowIndex, colIndex) } if (!arr.length) { emit('blur', { val, field: item.field, rowIndex, colIndex }) // 触发 clearIsError(rowIndex, colIndex) } } const change = (val: any, item: typeof fieldProperty, rowIndex: number, colIndex: number) => { let arr: Array<boolean> = [] if (item.property.rules && isArray(item.property.rules)) { arr = validateForField(item, val, 'change', rowIndex, colIndex) } if (!arr.length) { emit('change', { val, field: item.field, rowIndex, colIndex }) // 触发 clearIsError(rowIndex, colIndex) } } const isError = ref<{rowIndex: number, colIndex: number}[]>([]) const validateForField = (item: typeof fieldProperty, val: any, type: string, rowIndex: number, colIndex: number) => { let arr: Array<boolean> = [] item.property.rules.forEach((valid) => { const types = [valid.trigger, noType] if (valid.required && !val) { ElMessage.error(valid.message) arr.push(false) isError.value.push({ rowIndex, colIndex, }) return } if (!valid.required && !val || !types.includes(type)) return if (!valid.validator) return const bool = valid.validator(val) if (!bool) { ElMessage.error(valid.message) arr.push(bool) isError.value.push({ rowIndex, colIndex, }) } }) return arr } const clearIsError = (rowIndex: number, colIndex: number) => { if (rowIndex === -1) { isError.value = [] } else { isError.value = isError.value.filter((item) => { return !((item.rowIndex === rowIndex) && (item.colIndex === colIndex)) }) } } const validate = () => { let arr: Array<boolean> = [] clearIsError(-1, -1) tableData.value.forEach((data: object, rowIndex: number) => { tableProperty.value.forEach((tabPro: any, colIndex: number) => { if (!tabPro.property.rules) return const field = tabPro.field as keyof typeof data arr.push(...validateForField(tabPro, data[field], noType, rowIndex, colIndex)) }); }); return !arr.length } const getIsErrorClass = computed(() => { return (rowIndex: number, colIndex: number) => { let bool = false isError.value.forEach((error) => { (error.rowIndex === rowIndex) && (error.colIndex === colIndex) && (bool = true) }) return bool ? 'is-error' : '' } }) const getTableHeader = (rules: rulesType[]) => { if (!rules) return '' return !!rules.filter((item) => item.required).length ? 'table_header' : '' } return { tableRef, tablemaxHeight, tableProperty, tableData, isError, getIsErrorClass, getTableHeader, change, blur, validate }; }, }); 二、使用步骤 <TableConfiguration ref="supplierListRef" v-model:data="supplierListEntity.product" :hasSelection="true" :selectionFixed="true" :property="tableProperty" align="center" /> import { defineComponent, reactive, ref } from 'vue' import TableConfiguration from '@/components/table-configuration/index.vue' export default defineComponent({ components: { TableConfiguration }, setup() { const tableRef = ref() const tableProperty = reactive([ { label: 'Input01', type: 'Input', field: 'Input01', property: { maxlength: 500, rules: [{ required: false, message: 'error', trigger: 'blur', validator: (value: string) => { return /^\+?[1-9][0-9]*$/.test(value) }}] }}, { label: 'Input02', type: 'Input', field: 'Input02', width: '200px', property: { maxlength: 500, rules: [{ required: true, message: 'error', trigger: 'blur' }] }} ]) const tableEntity = reactive({ table: [{ Input01: '', Input02: '', }] }) const validate = () => { tableRef.value.validate() } return { tableRef, tableProperty, tableEntity, validate } }, })
基于element-plus定义表格行内编辑配置化由讯客互联创业栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“基于element-plus定义表格行内编辑配置化”