vue3+element表格封装支持多级表头和行内编辑

1,172 阅读1分钟

基于之前的封装的table组件增加多级表头和行内编辑功能

多级表头

其实就是递归 el-table-column 和 slots 嵌套的问题

重新封装一下 table-column,如果是多级表头的话就递归一下

<!-- ProTableColumn.vue -->
<template v-if="column.children && column.children.length > 0">
  <pro-table-column
    v-for="(child, index) in column.children"
    :key="`pro-table-column__${child.prop || child.label || index}`"
    :column="child"
  >
    <template v-for="(_, slot) in $slots" :key="slot" #[slot]="slotScope">
      <slot :name="slot" v-bind="slotScope" />
    </template>
  </pro-table-column>
</template>
<!-- ProTable.vue -->
<el-table
  ref="tableRef"
  v-loading="loading"
  :data="tableData"
  :row-key="rowKey"
  :current-row-key="rowKey"
  @selection-change="onSelectionChange"
  v-bind="$attrs"
>
  <pro-table-column
    v-for="column in computedColumns"
    v-show="!column.hidden || !column.hideInTable"
    :key="column.prop"
    :column="column"
  >
    <template v-for="(_, slot) in $slots" #[slot]="scope">
      <slot :name="slot" v-bind="scope" />
    </template>
  </pro-table-column>
</el-table>

效果

image.png

新增支持行内编辑和表单校验

修改一下 ProTableColumn 组件,如果是 edit 状态就返回一个 form-item

需要注意的是 form-item 的 prop 是 name.index.prop,在 form-item 绑定 prop 时 和 validateFields 时要一致,否则不会触发校验

<pro-form-item
  v-if="
    scope.row.isEdit &&
    ('editable' in column ? column?.editable : true) &&
    column.prop
  "
  :field="omit(column, ['prop', 'label'])"
  label=""
  :rules="rules?.[column.prop]"
  :prop="`${formItem?.prop || 'tableData'}.${scope.$index}.${column.prop}`"
  :component="column.formItemComponent || column.component"
  v-model="scope.row[column.prop]"
></pro-form-item>

自定义组件触发 form-item 的 规则校验,需要通过 useFormItem hook

获取到 formItem 实例,在 modelValue 修改的时候调用 formItem?.validate('change')

import { useFormItem } from 'element-plus'

const { formItem, form } = useFormItem()

emit('update:modelValue', unref(tableData) as T[])
formItem?.validate('change', (isValid, errors) => {
  console.log(isValid, errors)
})
formItem?.validate('blur')

效果

image.png

可以嵌套在el-form表单中使用

<el-form :model="formValues" ref="formRef" :rules="formRules">
    <el-form-item label="名称">
      <el-input v-model="formValues.name" />
    </el-form-item>
    <el-form-item prop="list" label="列表数据">
      <field-editable-pro-table
        ref="editableTableRef"
        :columns="columns"
        :stripe="true"
        :operation="{
          actions: ['ok', 'edit', 'cancel', 'delete'],
        }"
        :page-config="false"
        :creatorProps="{ defaultRecord } as any"
        :searchable="false"
        :rules="rules"
        v-model="formValues.list"
      >
      </field-editable-pro-table>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="submit(formRef)">提交</el-button>
    </el-form-item>
 </el-form>

image.png

学习到了~~ el-form 的 useFormItem hook 通过 provide 和 inject 实现的