Crud

封装表格组件和表单组件实现通过配置动态生成 Crud 页面,支持表格和表单组件的全部属性

提示

Crud 组件是 Table Form Descriptions 的合并,在使用前最好先熟悉这些组件使用

使用

基础用法

当 columns 绑定的是一个具有响应式的数组时,数组的变动会影响 Crud 变动(及动态 Crud)。如果不需要动态 Crud 推荐绑定一个普通数组

根据 add edit form hide search detail 自动生成多功能表格

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
    @search="search"
    @submit="submit"
    @delete="deleteRow"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'

export default defineComponent({
  setup() {
    const form = ref({})
    const serachForm = ref({})
    const detail = ref({})
    const columns = [
      {
        label: 'Date',
        prop: 'date',
        component: 'el-input',
        add: true,
        edit: true,
        search: true,
        detail: true,
      },
      {
        label: 'Name',
        prop: 'name',
        component: 'el-input',
        add: true,
        search: true,
        detail: true,
      },
      {
        label: 'Address',
        prop: 'address',
        component: 'el-input',
        add: true,
        edit: true,
        detail: true,
      },
    ]
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = (done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    }

    const search = (done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    }

    const submit = (close, done, type, isValid, invalidFields) => {
      ElMessage(`submit: ${type}, ${isValid}`)
      console.log('submit', form.value, type, isValid, invalidFields)
      setTimeout(() => {
        isValid ? close() : done()
      }, 1000)
    }

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      form,
      serachForm,
      detail,
      data,
      columns,
      beforeOpen,
      search,
      submit,
      deleteRow,
    }
  },
})
</script>

智能提示

通过辅助函数 defineCrudColumns defineCrudMenuColumns defineCrudBeforeOpen defineCrudBeforeClose defineCrudSearch defineCrudSubmit 提供智能提示

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
    @search="search"
    @submit="submit"
    @delete="deleteRow"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineCrudSearch,
  defineCrudBeforeOpen,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const serachForm = ref({})
    const detail = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
        component: 'el-input',
        add: true,
        edit: true,
        search: true,
        detail: true,
      },
      {
        label: 'Name',
        prop: 'name',
        component: 'el-input',
        add: true,
        search: true,
        detail: true,
      },
      {
        label: 'Address',
        prop: 'address',
        component: 'el-input',
        add: true,
        edit: true,
        detail: true,
      },
    ])
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const search = defineCrudSearch((done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      form,
      serachForm,
      columns,
      data,
      detail,
      beforeOpen,
      search,
      submit,
      deleteRow,
    }
  },
})
</script>

嵌套键值

支持直接对具有嵌套结构的对象或数组进行取值或赋值,仅需要配置 prop

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
    @search="search"
    @submit="submit"
    @delete="deleteRow"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudBeforeOpen,
  defineCrudSubmit,
  defineCrudSearch,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({ 'a.b': undefined })
    const serachForm = ref({ 'a.b': undefined })
    const detail = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Break',
        prop: 'a.b',
        component: 'el-input',
        form: true,
        search: true,
        detail: true,
      },
      {
        label: 'Object',
        prop: 'a.b.c',
        component: 'el-input',
        form: true,
        search: true,
        detail: true,
      },
      {
        label: 'Array',
        prop: 'b[0]',
        component: 'el-input',
        form: true,
        search: true,
        detail: true,
      },
    ])
    const data = [
      {
        'a.b': 'break nested value',
        a: { b: { c: 'nested value c' } },
        b: ['nested value in array'],
      },
    ]

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      } else {
        form.value = { 'a.b': undefined }
      }
      done()
    })

    const search = defineCrudSearch((done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      form,
      serachForm,
      data,
      detail,
      columns,
      beforeOpen,
      search,
      submit,
      deleteRow,
    }
  },
})
</script>

配置按钮

默认不显示新增、编辑、删除按钮,需要配置 menu 或者启用 menu 插槽时才会显示

按钮也可以通过 国际化 来配置

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :menu="menu"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
    @search="search"
    @search-reset="reset"
    @submit="submit"
    @reset="reset"
    @delete="deleteRow"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudMenuColumns,
  defineCrudSubmit,
  defineCrudSearch,
  defineCrudBeforeOpen,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const menu = defineCrudMenuColumns({
      label: 'Operations',
      addText: 'New',
      detailText: 'View Row',
      editText: 'Edit Row',
      delText: 'Remove',
      searchText: 'Search',
      searchResetText: 'Reset Search',
      submitText: 'Create',
      resetText: 'Reset Form',
      detail: (row) => row.date !== '2016-05-02',
      edit: (row) => row.date !== '2016-05-03',
      del: (row) => row.date !== '2016-05-04',
      searchReset: false,
      detailProps: { type: 'success', plain: true },
      editProps: { type: 'default', plain: true },
      delProps: { type: 'info', plain: true },
    })
    const form = ref({})
    const serachForm = ref({})
    const detail = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
        component: 'el-input',
        form: true,
        detail: true,
      },
      {
        label: 'Name',
        prop: 'name',
        component: 'el-input',
        form: true,
        search: true,
        detail: true,
      },
      {
        label: 'Address',
        prop: 'address',
        component: 'el-input',
        form: true,
        detail: true,
      },
    ])
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-04',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-01',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const search = defineCrudSearch((done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const reset = () => {
      ElMessage('reset')
      console.log('reset')
    }

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      form,
      serachForm,
      columns,
      menu,
      data,
      detail,
      beforeOpen,
      search,
      submit,
      reset,
      deleteRow,
    }
  },
})
</script>

指定搜索表单

通过 search-columns 传入的配置直接作用于搜索表单,类型同 Form columns

暂无数据
<template>
  <pro-crud
    v-model:search="serachForm"
    :columns="columns"
    :search-columns="searchColumns"
    @search="search"
    @search-reset="reset"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudSearch,
  defineFormColumns,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const serachForm = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
      },
      {
        label: 'Name',
        prop: 'name',
      },
      {
        label: 'Address',
        prop: 'address',
      },
    ])
    const searchColumns = defineFormColumns([
      {
        label: 'Name',
        prop: 'name',
        component: 'el-input',
      },
      {
        label: 'Date',
        prop: 'date',
        component: 'el-date-picker',
        props: {
          type: 'datetimerange',
          rangeSeparator: '-',
          startPlaceholder: 'start',
          endPlaceholder: 'end',
        },
      },
    ])

    const search = defineCrudSearch((done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    })

    const reset = () => {
      ElMessage('reset search')
      console.log('reset search')
    }

    return {
      serachForm,
      columns,
      searchColumns,
      search,
      reset,
    }
  },
})
</script>

指定新增表单

通过 add-columns 传入的配置直接作用于新增表单,类型同 Form columns

暂无数据
<template>
  <pro-crud
    v-model="form"
    :columns="columns"
    :add-columns="addColumns"
    :menu="true"
    label-width="100px"
    @submit="submit"
    @reset="reset"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineFormColumns,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
      },
      {
        label: 'Name',
        prop: 'name',
      },
      {
        label: 'Address',
        prop: 'address',
      },
    ])
    const addColumns = defineFormColumns([
      {
        label: 'Name',
        prop: 'name',
        component: 'el-input',
      },
      {
        label: 'Date',
        prop: 'date',
        component: 'el-date-picker',
        props: {
          type: 'datetimerange',
          rangeSeparator: '-',
          startPlaceholder: 'start',
          endPlaceholder: 'end',
        },
      },
    ])

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const reset = () => {
      ElMessage('reset')
      console.log('reset')
    }

    return {
      form,
      columns,
      addColumns,
      submit,
      reset,
    }
  },
})
</script>

指定编辑表单

通过 edit-columns 传入的配置直接作用于新增表单,类型同 Form columns

<template>
  <pro-crud
    v-model="form"
    :columns="columns"
    :edit-columns="editColumns"
    :menu="true"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
    @submit="submit"
    @reset="reset"
    @delete="deleteRow"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineFormColumns,
  defineCrudBeforeOpen,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const detail = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
        component: 'el-input',
        add: true,
        detail: true,
      },
      {
        label: 'Name',
        prop: 'name',
        detail: true,
      },
      {
        label: 'Address',
        prop: 'address',
        detail: true,
      },
    ])
    const editColumns = defineFormColumns([
      {
        label: 'Name',
        prop: 'name',
        component: 'el-input',
      },
      {
        label: 'Date',
        prop: 'date',
        component: 'el-date-picker',
        props: {
          type: 'datetimerange',
          rangeSeparator: '-',
          startPlaceholder: 'start',
          endPlaceholder: 'end',
        },
      },
    ])
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const reset = () => {
      ElMessage('reset')
      console.log('reset')
    }

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      form,
      columns,
      detail,
      editColumns,
      data,
      beforeOpen,
      submit,
      reset,
      deleteRow,
    }
  },
})
</script>

指定表单

通过 form-columns 传入的配置直接作用于新增和编辑表单,类型同 Form columns

<template>
  <pro-crud
    v-model="form"
    :columns="columns"
    :form-columns="formColumns"
    :menu="true"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
    @submit="submit"
    @reset="reset"
    @delete="deleteRow"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineFormColumns,
  defineCrudBeforeOpen,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const detail = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
        detail: true,
      },
      {
        label: 'Name',
        prop: 'name',
        detail: true,
      },
      {
        label: 'Address',
        prop: 'address',
        detail: true,
      },
    ])
    const formColumns = defineFormColumns([
      {
        label: 'Name',
        prop: 'name',
        component: 'el-input',
      },
      {
        label: 'Date',
        prop: 'date',
        component: 'el-date-picker',
        props: {
          type: 'datetimerange',
          rangeSeparator: '-',
          startPlaceholder: 'start',
          endPlaceholder: 'end',
        },
      },
    ])
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = {
          name: row.name,
          date: [],
        }
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const reset = () => {
      ElMessage('reset')
      console.log('reset')
    }

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      form,
      columns,
      formColumns,
      data,
      detail,
      beforeOpen,
      submit,
      reset,
      deleteRow,
    }
  },
})
</script>

指定详情

通过 detail-columns 传入的配置直接作用于详情,类型同 Descriptions columns

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :detail-columns="detailColumns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
    @search="search"
    @submit="submit"
    @delete="deleteRow"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineCrudSearch,
  defineCrudBeforeOpen,
  defineDescriptionsColumns,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const serachForm = ref({})
    const detail = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
        component: 'el-input',
        form: true,
      },
      {
        label: 'Name',
        prop: 'name',
      },
    ])
    const detailColumns = defineDescriptionsColumns([
      {
        label: 'Date',
        prop: 'date',
      },
      {
        label: 'Name',
        prop: 'name',
      },
      {
        label: 'Address',
        prop: 'address',
      },
    ])
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const search = defineCrudSearch((done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      form,
      serachForm,
      columns,
      detailColumns,
      data,
      detail,
      beforeOpen,
      search,
      submit,
      deleteRow,
    }
  },
})
</script>

指定表格

通过 table-columns 传入的配置直接作用于表格,类型同 Table columns

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :table-columns="tableColumns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
    @submit="submit"
    @reset="reset"
    @delete="deleteRow"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineTableColumns,
  defineCrudBeforeOpen,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const serachForm = ref({})
    const detail = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
        component: 'el-input',
        form: true,
        detail: true,
      },
      {
        label: 'Name',
        prop: 'name',
        component: 'el-input',
        form: true,
        search: true,
        detail: true,
      },
      {
        label: 'Address',
        prop: 'address',
        component: 'el-input',
        detail: true,
      },
    ])
    const tableColumns = defineTableColumns([
      {
        label: 'Date',
        prop: 'date',
      },
      {
        label: 'User',
        children: [
          {
            label: 'Name',
            prop: 'name',
          },
          {
            label: 'Address',
            prop: 'address',
          },
        ],
      },
    ])
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const reset = () => {
      console.log('reset')
    }

    const deleteRow = (row) => {
      console.log('deleteRow', row)
    }

    return {
      form,
      serachForm,
      columns,
      tableColumns,
      data,
      detail,
      beforeOpen,
      submit,
      reset,
      deleteRow,
    }
  },
})
</script>

弹窗前后

通过 before-open before-close 指定弹窗开启前与弹窗关闭前执行的操作

<template>
  <pro-crud
    v-model="form"
    :columns="columns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    :before-close="beforeClose"
    label-width="100px"
    @delete="deleteRow"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudBeforeOpen,
  defineCrudBeforeClose,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const detail = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
        component: 'el-input',
        form: true,
        detail: true,
      },
      {
        label: 'Name',
        prop: 'name',
        detail: true,
      },
      {
        label: 'Address',
        prop: 'address',
        detail: true,
      },
    ])
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      ElMessage(`beforeOpen: ${type}`)
      console.log('beforeOpen', type, row)
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const beforeClose = defineCrudBeforeClose((done) => {
      ElMessage('beforeClose')
      console.log('beforeClose')
      done()
    })

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      form,
      columns,
      data,
      detail,
      beforeOpen,
      beforeClose,
      deleteRow,
    }
  },
})
</script>

打开弹窗

通过组件暴露的 openDialog 方法可以打开弹窗

<template>
  <pro-crud
    ref="crudRef"
    v-model="form"
    :columns="columns"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
  >
    <template #menu-right="{ size }">
      <el-button
        :size="size"
        @click="crudRef.openDialog('add')"
      >
        open
      </el-button>
      <el-button
        :size="size"
        @click="crudRef.openDialog('edit', data[0])"
      >
        edit
      </el-button>
      <el-button
        :size="size"
        @click="crudRef.openDialog('detail', data[0])"
      >
        detail
      </el-button>
    </template>
    <template #form-menu-right="{ size }">
      <el-button
        :size="size"
        @click="crudRef.closeDialog()"
      >
        close
      </el-button>
    </template>
  </pro-crud>
</template>

<script>
import { defineComponent, ref } from 'vue'
import { defineCrudColumns, defineCrudBeforeOpen } from 'element-pro-components'

export default defineComponent({
  setup() {
    const crudRef = ref()
    const form = ref({})
    const detail = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
        component: 'el-input',
        form: true,
        detail: true,
      },
      {
        label: 'Name',
        prop: 'name',
        detail: true,
      },
      {
        label: 'Address',
        prop: 'address',
        detail: true,
      },
    ])
    const data = [
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ]

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    return {
      crudRef,
      form,
      columns,
      data,
      detail,
      beforeOpen,
    }
  },
})
</script>

插槽

columns 中配置 render 可以使用简单的 渲染函数。或者直接在模版中增加带 [prop] 相关的插槽

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    selection
    label-width="100px"
    @search="search"
    @submit="submit"
    @delete="deleteRow"
  >
    <template #menu-left="{ size }">
      <el-button
        :size="size"
        type="primary"
      >
        menu-left
      </el-button>
    </template>
    <template #menu-right="{ size }">
      <el-button
        :size="size"
        type="danger"
      >
        menu-right
      </el-button>
    </template>
    <template #menu="{ size }">
      <el-button
        :size="size"
        type="success"
        link
      >
        More
      </el-button>
    </template>
    <template #search-menu-right="{ size }">
      <el-button
        :size="size"
        type="success"
      >
        search-menu-right
      </el-button>
    </template>
    <template #action>
      <el-button
        :icon="Refresh"
        circle
        style="margin-right: 8px"
      />
      <pro-column-setting v-model="columns" />
    </template>
    <template #dialog-top="{ type }">
      <p style="text-align: center">
        dialog-top {{ type }}
      </p>
    </template>
    <template #dialog-bottom="{ type }">
      <p
        v-if="type === 'detail'"
        style="text-align: center"
      >
        only appears in the detail
      </p>
    </template>
    <template #form-name>
      <span>form slot</span>
    </template>
    <template #detail-name="{ item, size }">
      <el-tag :size="size">
        {{ item?.name }}
      </el-tag>
    </template>
    <template #table-name="{ row, size }">
      <el-tag :size="size">
        {{ row?.name }}
      </el-tag>
    </template>
    <template #table-name-header="{ column }">
      <s>{{ column.label }}</s>
    </template>
  </pro-crud>
</template>

<script>
import { defineComponent, h, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { Clock, Refresh } from '@element-plus/icons-vue'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineCrudSearch,
  defineCrudBeforeOpen,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const serachForm = ref({})
    const detail = ref({})
    const columns = ref(
      defineCrudColumns([
        {
          label: 'Date',
          prop: 'date',
          component: 'el-input',
          add: true,
          edit: true,
          search: true,
          detail: true,
          render: '--',
          props: {
            slots: {
              suffix: () =>
                h('span', { className: 'el-input__icon' }, h(Clock)),
            },
          },
        },
        {
          label: 'Name',
          prop: 'name',
          component: 'el-input',
          add: true,
          search: true,
          detail: true,
        },
        {
          label: 'Address',
          prop: 'address',
          component: 'el-input',
          add: true,
          edit: true,
          render: (row) => h('em', null, row.address),
        },
      ])
    )
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const search = defineCrudSearch((done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      Refresh,
      form,
      columns,
      serachForm,
      data,
      detail,
      beforeOpen,
      search,
      submit,
      deleteRow,
    }
  },
})
</script>

<style>
.el-input__icon {
  width: 14px;
}
</style>

自定义表单内容

一些情况下默认表单可能无法满足需求,可以通过 crud-search crud-form 插槽可以自定义表单内容

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    selection
    label-width="100px"
    @search="search"
    @submit="submit"
    @delete="deleteRow"
  >
    <template #crud-search="{ props }">
      <pro-form
        v-bind="props"
        :inline="false"
        label-width="100px"
        style="margin-bottom: 18px"
      />
    </template>
    <template #crud-form="{ props }">
      <pro-form
        v-bind="props"
        :inline="true"
      />
    </template>
  </pro-crud>
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { Refresh } from '@element-plus/icons-vue'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineCrudSearch,
  defineCrudBeforeOpen,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const serachForm = ref({})
    const detail = ref({})
    const columns = ref(
      defineCrudColumns([
        {
          label: 'Date',
          prop: 'date',
          component: 'el-input',
          add: true,
          edit: true,
          search: true,
          detail: true,
        },
        {
          label: 'Name',
          prop: 'name',
          component: 'el-input',
          add: true,
          search: true,
          detail: true,
        },
        {
          label: 'Address',
          prop: 'address',
          component: 'el-input',
          add: true,
          edit: true,
        },
      ])
    )
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const search = defineCrudSearch((done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      Refresh,
      form,
      columns,
      serachForm,
      data,
      detail,
      beforeOpen,
      search,
      submit,
      deleteRow,
    }
  },
})
</script>

<style>
.el-input__icon {
  width: 14px;
}
</style>

自定义列表内容

组件内部默认使用 ProTable 渲染列表,但对于一些特殊情况,使用 ProTable 并不能够更好的展现数据。通过 crud-table 插槽可以自定义列表内容

qiang

address: No. 189, Grove St, Los Angeles

creation date: 2016-05-03

qiang

address: No. 189, Grove St, Los Angeles

creation date: 2016-05-02

  • 1
前往
共 2 条
<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    selection
    label-width="100px"
    @search="search"
    @submit="submit"
    @delete="deleteRow"
  >
    <template #crud-table="{ showMenu, createTableMenu }">
      <section class="list">
        <div
          v-for="item in data"
          :key="item.name"
          class="item"
        >
          <div class="item-content">
            <el-image
              :src="item.avatar"
              fit="cover"
              class="item-avatar"
            />
            <div class="item-info">
              <p class="name">
                {{ item.name }}
              </p>
              <p>address: {{ item.address }}</p>
              <p>creation date: {{ item.date }}</p>
            </div>
          </div>
          <div class="item-menu">
            <component
              :is="() => createTableMenu({ row: item })"
              v-if="showMenu"
            />
          </div>
        </div>
      </section>
      <el-pagination
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :total="total"
      />
    </template>
    <template #crud-detail>
      <div class="detail">
        <el-image
          :src="detail.avatar"
          fit="cover"
          class="item-avatar"
        />
        <div class="item-info">
          <p class="name">
            {{ detail.name }}
          </p>
          <p>address: {{ detail.address }}</p>
          <p>creation date: {{ detail.date }}</p>
        </div>
      </div>
    </template>
  </pro-crud>
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { Refresh } from '@element-plus/icons-vue'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineCrudSearch,
  defineCrudBeforeOpen,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const serachForm = ref({})
    const currentPage = ref(1)
    const pageSize = ref(10)
    const total = ref(2)
    const detail = ref({})
    const columns = ref(
      defineCrudColumns([
        {
          label: 'Date',
          prop: 'date',
          component: 'el-input',
          add: true,
          edit: true,
          search: true,
          detail: true,
        },
        {
          label: 'Name',
          prop: 'name',
          component: 'el-input',
          add: true,
          search: true,
          detail: true,
        },
        {
          label: 'Address',
          prop: 'address',
          component: 'el-input',
          add: true,
          edit: true,
        },
      ])
    )
    const data = ref([
      {
        avatar: 'https://avatars.githubusercontent.com/u/23313167?v=4',
        date: '2016-05-03',
        name: 'qiang',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        avatar: 'https://avatars.githubusercontent.com/u/23313167?v=4',
        date: '2016-05-02',
        name: 'qiang',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const search = defineCrudSearch((done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      Refresh,
      form,
      columns,
      serachForm,
      data,
      currentPage,
      pageSize,
      total,
      detail,
      beforeOpen,
      search,
      submit,
      deleteRow,
    }
  },
})
</script>

<style scoped>
.list {
  margin-top: calc(var(--el-component-size) / 2);
}
.list .item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: calc(var(--el-component-size) / 2) 0;
}
.list .item .item-content {
  display: flex;
}
.list .item .item-content .item-avatar {
  margin-right: var(--el-component-size);
  width: 100px;
  height: 100px;
  border-radius: 50%;
}

.item-info {
  display: flex;
  flex-direction: column;
  justify-content: space-around;
}
.item-info p {
  margin: 0;
  padding: 0;
}
.item-info .name {
  font-size: 22px;
  font-weight: bold;
}

.detail {
  display: flex;
  justify-content: center;
}
.detail .item-avatar {
  margin-right: 100px;
  width: 150px;
  height: 150px;
  border-radius: 50%;
}
</style>

自定义弹窗

组件内部默认使用 ElDialog 作为弹窗,可以通过 crud-dialog 插槽实现自定义弹窗

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :column="1"
    :before-open="beforeOpen"
    selection
    label-width="100px"
    @search="search"
    @submit="submit"
    @delete="deleteRow"
  >
    <template #crud-dialog="{ type, props, createDescriptions, createForm }">
      <el-drawer v-bind="props">
        <component
          :is="type === 'detail' ? createDescriptions() : createForm()"
        />
      </el-drawer>
    </template>
  </pro-crud>
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { Refresh } from '@element-plus/icons-vue'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineCrudSearch,
  defineCrudBeforeOpen,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const serachForm = ref({})
    const detail = ref({})
    const columns = ref(
      defineCrudColumns([
        {
          label: 'Date',
          prop: 'date',
          component: 'el-input',
          add: true,
          edit: true,
          search: true,
          detail: true,
        },
        {
          label: 'Name',
          prop: 'name',
          component: 'el-input',
          add: true,
          search: true,
          detail: true,
        },
        {
          label: 'Address',
          prop: 'address',
          component: 'el-input',
          add: true,
          edit: true,
        },
      ])
    )
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const search = defineCrudSearch((done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      Refresh,
      form,
      columns,
      serachForm,
      data,
      detail,
      beforeOpen,
      search,
      submit,
      deleteRow,
    }
  },
})
</script>

<style>
.el-input__icon {
  width: 14px;
}
</style>

TypeScript

defineCrudColumns 支持传入一个泛型用来推断 prop

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :menu="menu"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
    @search="search"
    @submit="submit"
    @delete="deleteRow"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudMenuColumns,
  defineCrudSubmit,
  defineCrudSearch,
  defineCrudBeforeOpen,
} from 'element-pro-components'

interface DataItem {
  date: string
  name: string
  address: string
}

const form = ref({})
const serachForm = ref({})
const detail = ref({})
const menu = defineCrudMenuColumns<DataItem>({
  label: 'Operations',
  edit: (row) => row.date !== '2016-05-02',
  del: (row) => row.date !== '2016-05-04',
  searchReset: false,
})
const columns = defineCrudColumns<DataItem>([
  {
    label: 'Date',
    prop: 'date',
    component: 'el-input',
    add: true,
    edit: true,
    search: true,
    detail: true,
  },
  {
    label: 'Name',
    prop: 'name',
    component: 'el-input',
    add: true,
    search: true,
    detail: true,
  },
  {
    label: 'Address',
    prop: 'address',
    component: 'el-input',
    add: true,
    edit: true,
    detail: true,
  },
])
const data = ref<DataItem[]>([
  {
    date: '2016-05-03',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-02',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
])

const beforeOpen = defineCrudBeforeOpen<DataItem>((done, type, row) => {
  if (type === 'edit') {
    form.value = row || {}
  } else if (type === 'detail') {
    detail.value = row || {}
  }
  done()
})

const search = defineCrudSearch((done, isValid, invalidFields) => {
  ElMessage(`search: ${isValid}`)
  console.log('search', serachForm.value, isValid, invalidFields)
  setTimeout(() => {
    done()
  }, 1000)
})

const submit = defineCrudSubmit((close, done, type, isValid, invalidFields) => {
  ElMessage(`submit: ${type}, ${isValid}`)
  console.log('submit', form.value, type, isValid, invalidFields)
  setTimeout(() => {
    isValid ? close() : done()
  }, 1000)
})

const deleteRow = (row: DataItem) => {
  ElMessage('deleteRow')
  console.log('deleteRow', row)
}
</script>

配置

参数说明类型可选值默认值
v-model表单绑定值object--
v-model:search搜索表单绑定值object--
columns自动生成 Crud 的参数,参考下面 columnsarray--
add-columns自动生成新增表单的参数,参考 Form columnsarray-columns 中获取
edit-columns自动生成编辑表单的参数,参考 Form columnsarray-columns 中获取
form-columns自动生成表单的参数,参考 Form columnsarray-columns 中获取
search-columns自动生成搜索表单的参数,参考 Form columnsarray-columns 中获取
table-columns自动生成表格的参数,参考 Table columnsarray-columns 中获取
detail-columns自动生成描述详情的参数,参考 Descriptions columnsarray-columns 中获取
menu按钮配置参考下面 menuobject--
search-rules搜索表单验证规则object--
data显示的数据array--
selection显示多选框,支持 columns 的配置boolean / object-false
index显示索引,支持 columns 的配置boolean / object-false
expand开启展开插槽,支持 columns 的配置boolean / object-false
menu开启操作按钮插槽,支持 columns 的配置boolean / object-false
show-overflow-tooltip当内容过长被隐藏时显示 tooltipboolean-false
align对齐方式stringleft / center / rightleft
header-align表头对齐方式stringleft / center / right同 align
heightTable 的高度string / number-自动高度
max-heightTable 的最大高度string / number--
stripe是否为斑马纹 tableboolean-false
border是否带有纵向边框boolean-false
sizeTable 的尺寸stringlarge / default /small-
fit列的宽度是否自撑开boolean-true
show-header是否显示表头boolean-true
highlight-current-row是否要高亮当前行boolean-false
current-row-key当前行的 key,只写属性string / number--
row-class-name为行增加 classNameFunction({row, rowIndex}) / string--
row-style为行增加 styleFunction({row, rowIndex}) / object--
cell-class-name为单元格增加 classNameFunction({row, column, rowIndex, columnIndex}) / string--
cell-style为单元格增加 styleFunction({row, column, rowIndex, columnIndex}) / object--
header-row-class-name为表头行增加 classNameFunction({row, rowIndex}) / string--
header-row-style为表头行增加 styleFunction({row, rowIndex}) / object--
header-cell-class-name为表头单元格增加 classNameFunction({row, column, rowIndex, columnIndex}) / string--
header-cell-style为表头单元格增加 styleFunction({row, column, rowIndex, columnIndex}) / object--
row-key行数据的 Key,使用 reserveSelection 功能时必填Function(row) / string--
empty-text空数据时显示的文本内容string-暂无数据
default-expand-all是否默认展开所有行boolean-false
expand-row-keysTable 目前的展开行,与 row-key 配合使用array--
default-sort默认的排序列的 prop 和顺序Objectorder: ascending, descendingascending
tooltip-effecttooltip effect 属性stringdark / light-
show-summary是否在表尾显示合计行boolean-false
sum-text合计行第一列的文本string-合计
summary-method自定义的合计计算方法Function({ columns, data })--
span-method合并行或列的计算方法Function({ row, column, rowIndex, columnIndex })--
select-on-indeterminate当仅有部分行被选中时,点击表头的多选框时的行为,配合 selection 使用boolean-true
indent展示树形数据时,树节点的缩进number-16
lazy是否懒加载子节点数据boolean--
load加载子节点数据的函数,lazy 为 true 时生效Function(row, treeNode, resolve)--
tree-props渲染嵌套数据的配置选项Object-{ hasChildren: ‘hasChildren’, children: ‘children’ }
table-layout设置表格单元、行和列的布局方式stringfixed / autofixed
scrollbar-always-on总是显示滚动条booleanfalse
flexible确保主轴的最小尺寸booleanfalse
v-model:current-page当前页数number--
v-model:page-size每页显示条目个数number--
total总条目数number--
page-count总页数 totalpage-count 设置任意一个就可以达到显示页码的功能;如果要支持 page-sizes 的更改,则需要使用 total 属性number--
small是否使用小型分页样式boolean-false
background是否为分页按钮添加背景色boolean-false
default-page-size每页显示条目数的初始值number--
pager-count设置最大页码按钮数。 页码按钮的数量,当总页数超过该值时会折叠number5 ≤ x ≤ 21 的奇数7
default-current-page当前页数的初始值number--
layout组件布局,子组件名用逗号分隔stringsizes / prev / pager / next / jumper / -> / total / slot‘prev, pager, next, jumper, ->, total’
page-sizes每页显示个数选择器的选项设置number[]-[10, 20, 30, 40, 50, 100]
popper-class每页显示个数选择器的下拉框类名string--
prev-text替代图标显示的上一页文字string--
next-text替代图标显示的下一页文字string--
disabled是否禁用分页boolean-false
hide-on-single-page只有一页时是否隐藏boolean--
rules表单验证规则object--
inline行内表单模式boolean-false
array是否启用数组表单boolean-
max限制数组表单的最大数量number--
label-position表单域标签的位置,如果值为 left 或者 right 时,则需要设置 label-widthstringright / left / topright
label-width表单域标签的宽度,例如 ‘50px’ 或 ‘auto’string--
label-suffix表单域标签的后缀string--
hide-required-asterisk是否显示必填字段的标签旁边的红色星号boolean-false
show-message是否显示校验错误信息boolean-true
inline-message是否以行内形式展示校验信息boolean-false
status-icon是否在输入框中显示校验结果反馈图标boolean-false
validate-on-rule-change是否在 rules 属性改变后立即触发一次验证boolean-true
size用于控制该表单内组件的尺寸stringlarge / default /small-
disabled是否禁用该表单内的所有组件boolean-false
gutter栅格间隔number-0
justifyflex 布局下的水平排列方式stringstart / end / center / space-around / space-between / spacing-evenlystart
title弹窗的标题string-从 menu 中获取
width弹窗的宽度string / number-50%
fullscreen是否为全屏弹窗boolean-false
top弹窗 CSS 中的 margin-top 值string-15vh
modal是否需要遮罩层boolean-true
append-to-body弹窗自身是否插入至 body 元素上boolean-false
lock-scroll是否在 弹窗出现时将 body 滚动锁定boolean-true
open-delay弹窗打开的延时时间,单位毫秒number-0
close-delay弹窗关闭的延时时间,单位毫秒number-0
close-on-click-modal是否可以通过点击 modal 关闭弹窗boolean-true
close-on-press-escape是否可以通过按下 ESC 关闭弹窗boolean-true
show-close是否显示关闭按钮boolean-true
before-open弹窗开启前的回调,会暂停弹窗的开启Function(done, type, row)--
before-close关闭前的回调,会暂停弹窗的关闭Function(done)--
center是否对头部和底部采用居中布局boolean-false
detail显示的详情数据object--
border是否带有边框booleanfalse
column一行显示的数量number3
direction排列的方向stringvertical / horizontalhorizontal
size列表的尺寸stringlarge / default /small
extra操作区文本,显示在右上方string
align列的内容对齐方式(如无 border,对标签和内容均生效)stringleft / center / right-
label-align列的标签对齐方式,若不设置该项,则使用内容的对齐方式(如无 border,请使用 align 参数)stringleft / center / right

提示

Crud 支持 TableForm 的所有配置;支持 Descriptions 中除了 title 以外的事件属性,如果想要配置 title 请通过 descriptions-title 插槽实现;支持 ElDialog 除了 modelValue destroy-on-close 意外以外的属性,但不建议修改 title 和 width

部分属性名称相同,配置将传递给需要的组件

columns

参数说明类型可选值默认值
add是否在新增表单中显示boolean-false
edit是否在编辑表单中显示boolean-false
form是否在表单中显示boolean-false
search是否在搜索表单中显示boolean-false
detail是否在描述详情中显示boolean-false
hide是否在表格中隐藏boolean-false
prop对应 data 的字段名 (必填,需要是唯一值)string--
label显示的标题string--
slot是否开启自定义插槽功能boolean-false
render通过渲染函数对表格实现简单的插槽功能string / Function(row)--
children实现多级表头array--
columnKey当前项的 key,使用 filter-change 事件时需要string--
width对应列的宽度string--
minWidth对应列的最小宽度string--
fixed列是否固定,true 表示固定在左侧string / booleantrue / left / right-
renderHeader列标题 Label 区域渲染使用的 FunctionFunction(h, { column, $index })--
sortable对应列是否可以排序boolean / stringtrue / false / ‘custom’false
sortMethod对数据进行排序的时候使用的方法Function(a, b)--
sortBy指定数据按照哪个属性进行排序string / array / Function(row, index)--
sortOrders数据在排序时所使用排序策略的轮转顺序arrayascending 表示升序,descending 表示降序,null 表示还原为原始顺序[‘ascending’, ‘descending’, null]
resizable对应列是否可以通过拖动改变宽度,配合 border 使用boolean-true
formatter用来格式化内容Function(row, column, cellValue, index)--
showOverflowTooltip当内容过长被隐藏时显示 tooltipboolean-false
align对齐方式stringleft / center / rightleft
headerAlign表头对齐方式stringleft / center / right同 align
className列的 classNamestring--
labelClassName当前列标题的自定义类名string--
filters数据过滤的选项Array[{ text, value }]--
filterPlacement过滤弹出框的定位stringtop / top-start / top-end / bottom / bottom-start / bottom-end / left / left-start / left-end / right / right-start / right-end-
filterMultiple数据过滤的选项是否多选boolean-true
filterMethod数据过滤使用的方法Function(value, row, column)--
filteredValue选中的数据过滤项array--
index自定义索引,只能够在 index 中配置Function(index) / number--
selectable这一行的 CheckBox 是否可以勾选,只能够在 selection 中配置Function(row, index)--
reserveSelection是否保留之前选中的数据(需指定 row-key),只能够在 selection 中配置boolean-false
typechildren 内部表单的类型stringarray / group / tabs / collapse / stepsarray
max与 children 一起使用,限制子表单的最大数量number--
show是否在表单中显示当前项boolean-true
labelWidth表单域标签的宽度,例如 ‘50px’ 或 ‘auto’string--
required是否必填,如不设置,则会根据校验规则自动生成boolean-false
rules表单验证规则object / array--
error表单域验证错误信息, 设置该值会使表单验证状态变为error,并显示该错误信息string--
showMessage是否显示校验错误信息boolean-true
inlineMessage以行内形式展示校验信息boolean-false
size用于控制该表单域下组件的尺寸stringlarge / default /small-
span栅格占据的列数number-24
offset栅格左侧的间隔格数number-0
push栅格向右移动格数number-0
pull栅格向左移动格数number-0
xs<768px 响应式栅格数或者栅格属性对象number / object--
sm≥768px 响应式栅格数或者栅格属性对象number / object--
md≥992px 响应式栅格数或者栅格属性对象number / object--
lg≥1200px 响应式栅格数或者栅格属性对象number / object--
xl≥1920px 响应式栅格数或者栅格属性对象number / object--
disabled是否禁用, 当 type=tabs 或者 type=collapse 时生效booleanfalse
closable标签是否可关闭, 当 type=tabs 时生效booleanfalse
lazy标签是否延迟渲染, 当 type=tabs 时生效booleanfalse
description分步描述文案, 当 type=steps 时生效string
icon自定义分步图标, 当 type=steps 时生效string / Component
status设置当前步骤的状态, 当 type=steps 时生效stringwait / process / finish / error / success
detailSpan描述详情中列的数量number-1
width描述详情中列的宽度,不同行相同列的宽度按最大值设定(如无 border ,宽度包含标签与内容)string / number
minWidth描述详情中列的最小宽度,与 width 的区别是 width 是固定的,min-width 会把剩余宽度按比例分配给设置了 min-width 的列(如无 border,宽度包含标签与内容)string / number
align描述详情中列的内容对齐方式(如无 border,对标签和内容均生效)stringleft / center / rightleft
labelAlign描述详情中列的标签对齐方式,若不设置该项,则使用内容的对齐方式(如无 border,请使用 align 参数)stringleft / center / right
className描述详情中列的内容自定义类名string
labelClassName描述详情中列的标签自定义类名string
render描述详情中通过渲染函数实现简单的插槽功能Function(detail)--
renderLabel描述详情中通过渲染函数实现简单的 Label 插槽功能Function(column)--

提示

Crud columns 支持 Table columnsForm columns 的所有配置;支持 Descriptions columns 中除了 span 以外的事件属性,其中 span 需要改写成 detailSpan 使用

部分属性名称相同,配置将传递给需要的组件

参数说明类型默认值
add是否显示 add 按钮booleantrue
addTextadd 按钮显示的文字stringAdd
addPropsadd 按钮的配置,参考 el-buttonobject{ type: ‘primary’ }
edit是否显示 edit 按钮boolean / Function(row)true
editTextedit 按钮显示的文字stringEdit
editPropsedit 按钮的配置,参考 el-buttonobject{ link: true, type: ‘primary’ }
detail是否显示 detail 按钮boolean / Function(row)true
detailTextdetail 按钮显示的文字stringView
detailPropsdetail 按钮的配置,参考 el-buttonobject{ link: true, type: ‘info’ }
del是否显示 del 按钮boolean / Function(row)true
delTextdel 按钮显示的文字stringDelete
delPropsdel 按钮的配置,参考 el-buttonobject{ link: true, type: ‘danger’ }
submit是否显示 submit 按钮booleantrue
submitTextsubmit 按钮显示的文字stringSubmit
submitPropssubmit 按钮的配置,参考 el-buttonobject{ type: ‘primary’ }
reset是否显示 reset 按钮booleantrue
resetText是否显示 reset 按钮显示的文字stringReset
resetPropsreset 按钮的配置,参考 el-buttonobject-
prevTextprev 按钮显示的文字stringPrev
prevPropsprev 按钮的配置,参考 el-buttonobject-
nextTextnext 按钮显示的文字stringNext
nextPropsnext 按钮的配置,参考 el-buttonobject-
search是否显示 search 按钮booleantrue
searchTextsearch 按钮显示的文字stringSearch
searchPropssearch 按钮的配置,参考 el-buttonobject{ type: ‘primary’ }
searchReset是否显示 reset 按钮booleantrue
searchResetText是否显示 reset 按钮显示的文字stringReset
searchResetPropsreset 按钮的配置,参考 el-buttonobject-
searchPrevTextprev 按钮显示的文字stringPrev
searchPrevPropsprev 按钮的配置,参考 el-buttonobject-
searchNextTextnext 按钮显示的文字stringNext
searchNextPropsnext 按钮的配置,参考 el-buttonobject-

提示

其它属性同 Table columns

事件

事件名说明参数
submitsubmit 被点击后触发close, done, ‘add’/‘edit’, isValid, invalidFields
resetreset 按钮被点击后触发-
add-item表单中 add 被点击后触发indexes: number[]
remove-item表单中 remove 被点击后触发indexes: number[]
collapse-change表单中 collapse 改变时触发active: CollapseModelValue
tab-change表单中 tab 改变时触发name: TabPaneName
step-change表单中 step 改变时触发active: string | number
addadd 按钮被点击后触发-
editedit 按钮被点击后触发row
detaildetail 按钮被点击后触发row
deletedelete 按钮被点击后触发row
searchsearch 按钮被点击后触发done, isValid, invalidFields
searchResetsearch reset 按钮被点击后触发-
add-item搜索中 add 被点击后触发indexes: number[]
remove-item搜索中 remove 被点击后触发indexes: number[]
collapse-change搜索中 collapse 改变时触发active: CollapseModelValue
tab-change搜索中 tab 改变时触发name: TabPaneName
step-change搜索中 step 改变时触发active: string | number
loadpageSize 和 currentPage 改变时会触发-
select当用户手动勾选数据行的 Checkbox 时触发的事件selection, row
select-all当用户手动勾选全选 Checkbox 时触发的事件selection
selection-change当选择项发生变化时会触发该事件selection
cell-mouse-enter当单元格 hover 进入时会触发该事件row, column, cell, event
cell-mouse-leave当单元格 hover 退出时会触发该事件row, column, cell, event
cell-click当某个单元格被点击时会触发该事件row, column, cell, event
cell-dblclick当某个单元格被双击击时会触发该事件row, column, cell, event
row-click当某一行被点击时会触发该事件row, column, event
row-contextmenu当某一行被鼠标右键点击时会触发该事件row, column, event
row-dblclick当某一行被双击时会触发该事件row, column, event
header-click当某一列的表头被点击时会触发该事件column, event
header-contextmenu当某一列的表头被鼠标右键点击时触发该事件column, event
sort-change当表格的排序条件发生变化的时候会触发该事件{ column, prop, order }
filter-change当表格的筛选条件发生变化的时候会触发该事件,参数的值是一个对象,对象的 key 是 column 的 columnKey,对应的 value 为用户选择的筛选条件的数组。filters
current-change当表格的当前行发生变化的时候会触发该事件,如果要高亮当前行,请打开表格的 highlight-current-row 属性currentRow, oldCurrentRow
header-dragend当拖动表头改变了列的宽度的时候会触发该事件newWidth, oldWidth, column, event
expand-change当用户对某一行展开或者关闭的时候会触发该事件(展开行时,回调的第二个参数为 expandedRows;树形表格时第二参数为 expanded)row, (expandedRows | expanded)
validate任一表单项被校验后触发被校验的表单项 prop 值, isValid, invalidFields

方法

方法名说明参数
clearSelection用于多选表格,清空用户的选择-
toggleRowSelection用于多选表格,切换某一行的选中状态,如果使用了第二个参数,则是设置这一行选中与否(selected 为 true 则选中)row, selected
toggleAllSelection用于多选表格,切换全选和全不选-
toggleRowExpansion用于可展开表格与树形表格,切换某一行的展开状态,如果使用了第二个参数,则是设置这一行展开与否(expanded 为 truerow, expanded
setCurrentRow用于单选表格,设定某一行为选中行,如果调用时不加参数,则会取消目前高亮行的选中状态。row
clearSort用于清空排序条件,数据会恢复成未排序的状态-
clearFilter不传入参数时用于清空所有过滤条件,数据会恢复成未过滤的状态,也可传入由 columnKey 组成的数组以清除指定列的过滤条件columnKey
doLayout对 Table 进行重新布局。当 Table 或其祖先元素由隐藏切换为显示时,可能需要调用此方法-
sort手动对 Table 进行排序。参数prop属性指定排序列,order指定排序顺序。prop: string, order: string
validate对整个表单进行校验的方法,参数为一个回调函数。该回调函数会在校验结束后被调用,并传入两个参数:是否校验成功和未通过校验的字段。若不传入回调函数,则会返回一个 promiseFunction(callback: Function(boolean, object))
validateField对部分表单字段进行校验的方法Function(props: array | string, callback: Function(errorMessage: string))
resetFields对整个表单进行重置,将所有字段值重置为初始值并移除校验结果-
scrollToField滚动到指定表单字段Function(prop: string)
clearValidate移除表单项的校验结果。传入待移除的表单项的 prop 属性或者 prop 组成的数组,如不传则移除整个表单的校验结果Function(props: array | string)
openDialog打开弹窗Function(type: ICrudDialogType, row?: UnknownObject)
closeDialog关闭弹窗-

插槽

名称说明类型
crud-table自定义表格内容{ props, size, columns, menu, showMenu, createTableMenu }
crud-dialog自定义弹窗{ props, type, createForm, createDescriptions }
crud-search自定义搜索栏内容{ props, columns, menu }
crud-form自定义表单内容{ props, columns, menu }
crud-detail自定义描述内容{ props, columns, size }
menu-left新增按钮左侧{ size }
menu-right新增按钮右侧{ size }
action头部右侧操作栏{ size }
menu表格右侧自定义按钮{ size, row, column, $index }
dialog-top弹窗顶部内容{ type }
dialog-bottom弹窗底部内容{ type }
table在表格右侧菜单前插入的任意内容-
table-expand当 expand 为 true 时,配置展开显示的内容{ row, column, $index }
table-append插入至表格最后一行之后的内容-
table-[prop]当前这列的内容{ row, column, $index }
table-[prop]-header当前这列表头的内容{ column, $index }
form在表单底部按钮前插入的任意内容-
form-menu-left表单底部按钮左侧{ loading: boolean }
form-menu-right表单底部按钮右侧{ loading: boolean }
form-[prop]当前这项的 Form Item 的内容{ item: object, indexes?: number[], value: any, setValue: (value: any) => void }
form-[prop]-label当前这项的标签文本的内容{ item: object, indexes?: number[] }
form-[prop]-error当前这项的自定义表单校验信息的显示方式{ error, item: object, indexes?: number[] }
search在搜索按钮菜单前插入的任意内容-
search-menu-left搜索表单按钮左侧{ loading: boolean }
search-menu-right搜索表单按钮右侧{ loading: boolean }
search-[prop]当前这项的 Form Item 的内容{ item: object, indexes?: number[], value: any, setValue: (value: any) => void }
search-[prop]-label当前这项的标签文本的内容{ item: object, indexes?: number[] }
search-[prop]-error当前这项的自定义表单校验信息的显示方式{ error, item: object, indexes?: number[] }
detail在查看描述尾部插入更多的描述信息-
detail-title自定义描述标题文本,显示在左上方{ size }
detail-extra自定义描述操作区文本,显示在右上方{ size }
detail-[prop]当前描述这项的内容{ size, item }
detail-[prop]-label当前描述这项的标签文本内容{ size, item }

提示

[prop] 为 columns 中定义的 prop