element-plus table的简单封装

104 阅读1分钟

记录一下动态组件的封装,方便下次使用

上代码 !

<template>
  <el-table v-bind="attrs" :height="tableHeight" v-loading="loading" :data="tableData" border>
    <el-table-column
      v-for="column in columns"
      :key="column.prop"
      :label="column.label"
      v-bind="getColumnOptions(column)"
    >
      <template #default="scope">
        <!-- 支持组件/函数/插槽三种渲染方式 -->
        <slot v-if="column.slot" :name="column.slot" v-bind="{ ...scope }" />
        <component v-else-if="column.render" :is="column.render" v-bind="{ ...scope }" />
      </template>
    </el-table-column>
  </el-table>
</template>

<script setup lang="ts">
import { ElTable, ElTableColumn } from 'element-plus'
import { DefineComponent } from 'vue'
export type DynamicTableColumn = Partial<InstanceType<typeof ElTableColumn>> & {
  /**
   * 自定义渲染函数
   * @example
   * ```html
   * import { Fragment } from 'vue'
   *<Fragment>
   *  <ElButton
   *    onClick={() => {
   *      console.log(`e ==>`, row)
   *    }}
   *    link
   *    type="warning"
   *  >
   *    编辑
   *  </ElButton>
   *  <ElButton link type="danger">
   *    删除
   *  </ElButton>
   *</Fragment>
   * ```
   * @param scope
   */
  render?: (scope: { row: AnyObject; column: AnyObject; $index: number }) => DefineComponent
  /**
   * 是否使用插槽&对应插槽名称 如 slot:'name'
   * @example
   * ```vue
   * <template #name={xxx}>
   *
   * </template>
   * ```
   */
  slot?: string
  type?: 'selection' | 'index'
  align?: 'left' | 'center' | 'right'
}
type IProps = {
  tableData: any[]
  loading: boolean
  tableHeight: number
  columns: DynamicTableColumn[]
}
const props = withDefaults(defineProps<IProps>(), {
  tableHeight: 500,
})
console.log(`props ==>`,props);
type IEmit = {
  (e: 'selection-change', rows: any[]): any
}
const emit = defineEmits<IEmit>()
// 获取所有非 props 的属性和事件监听器
const attrs = useAttrs()
const slots = useSlots()
const getColumnOptions = (column: DynamicTableColumn): DynamicTableColumn => {
  return {
    ...column,
    align: column.align ? column.align : 'center',
    showOverflowTooltip: !column.showOverflowTooltip && !column.type ? true : false,
  }
}
</script>
<style lang="scss" scoped></style>

页面使用

<template>
  <div class="w-full h-full overflow-hidden p-[20px] pt-0">
    <ProTable>
      <template #table="{ tableHeight }">
        <DynamicTable
          :tableHeight="tableHeight"
          :tableData="tableData"
          :loading="loading"
          :columns="columns"
          @selection-change="(rows) => (tableCheck = rows)"
        >
          <template #option>
            <el-button link :type="buttonType.edit">编辑</el-button>
            <el-button link :type="buttonType.delete">删除</el-button>
          </template>
        </DynamicTable>
      </template>
      <template #pagination>
        <pagination
          v-model:page="queryParams.page"
          v-model:limit="queryParams.page_size"
          :total="total"
          :pageSizes="elConfig.pageSizes"
          small
          background
          :layout="elConfig.layout"
          @pagination="getList"
        />
      </template>
    </ProTable>
  </div>
</template>
<script lang="tsx" setup>
import ProTable from '@/components/ProTable/index.vue'
import { handleTableIndex } from '@/utils/handleTableIndex'
import { Fragment } from 'vue'  

/**表格数据 */
const tableData = ref<any[]>([])
const tableCheck = ref<any[]>([])
const columns = ref<DynamicTableColumn[]>([
  { type: 'selection', width: '50', align: 'center' },
  {
    label: '序号',
    width: '60',
    prop: '',
    formatter: (row, column, cellValue, index) => {
      return handleTableIndex(index, queryParams.page, queryParams.page_size) + ''
    },
  },
  { label: '用户编号', prop: '' },
  { label: '用户名称', prop: '' },
  { label: '用户地址', prop: '' },
  { label: '用户分类', prop: '' },
   {
    label: '来源',
    prop: '',
    render() {
      return (
        <Fragment>
          <ElButton
            onClick={() => {
              console.log(`e ==>`, row)
            }}
            link
            type="warning"
          >
            编辑
          </ElButton>
          <ElButton link type="danger">
            删除
          </ElButton>
        </Fragment>
      )
    },
  },
  { label: '标签名称', prop: '' },
  { label: '运行容量', prop: '' },
  { label: '合同容量', prop: '' },
  { label: '用能类型', prop: '' },
  { label: '供电所', prop: '' },
  { label: '创建时间', prop: '' },
  { label: '操作', slot: 'option' },
])

</script>
<style lang="scss" scoped></style>

image.png

ok!