Skip to content

Table 表格

静态数据渲染

1. 静态表单普通用法

代码示例

· 直接使用 ElPlusTable

vue
<ElPlusTable v-model="tableData" :tableConfig="tableConfig" :isPager="false" />
<ElPlusTable v-model="tableData" :tableConfig="tableConfig" :isPager="false" />

· setup 中

ts
let tableData = reactive([
  { id: 1, name: '张三', sex: '男', age: 55, address: '北京XXXX' },
  { id: 2, name: '李四', sex: '女', age: 24, address: '北京XXXX' },
  { id: 3, name: '王五', sex: '男', age: 4, address: '北京XXXX' }
])
const tableConfig = ref({
  column: [
    { prop: 'name', label: '名字' },
    { prop: 'sex', label: '性别' },
    { prop: 'age', label: '年龄' },
    { prop: 'address', label: '地址' }
  ]
} as ITableConfig)
let tableData = reactive([
  { id: 1, name: '张三', sex: '男', age: 55, address: '北京XXXX' },
  { id: 2, name: '李四', sex: '女', age: 24, address: '北京XXXX' },
  { id: 3, name: '王五', sex: '男', age: 4, address: '北京XXXX' }
])
const tableConfig = ref({
  column: [
    { prop: 'name', label: '名字' },
    { prop: 'sex', label: '性别' },
    { prop: 'age', label: '年龄' },
    { prop: 'address', label: '地址' }
  ]
} as ITableConfig)

· 使用字符串特性

不会使用?参考 FormatData 配置项

ts

let tableData = reactive([
  { id: 1, name: '张三', sex: 1, age: 55, address: '北京XXXX' },
  { id: 2, name: '李四', sex: 0, age: 24, address: '深圳XXXX' },
  { id: 3, name: '王五', sex: 1, age: 41, address: '上海XXXX' }
])

const tableConfig = ref({
  column: [
    { prop: 'name', label: '名字' },
    { prop: 'sex', label: '性别', format: 'formatSex' }, 
    { prop: 'age', label: '年龄' },
    { prop: 'address', label: '地址' }
  ]
} as ITableConfig)

let tableData = reactive([
  { id: 1, name: '张三', sex: 1, age: 55, address: '北京XXXX' },
  { id: 2, name: '李四', sex: 0, age: 24, address: '深圳XXXX' },
  { id: 3, name: '王五', sex: 1, age: 41, address: '上海XXXX' }
])

const tableConfig = ref({
  column: [
    { prop: 'name', label: '名字' },
    { prop: 'sex', label: '性别', format: 'formatSex' }, 
    { prop: 'age', label: '年龄' },
    { prop: 'address', label: '地址' }
  ]
} as ITableConfig)

2. 静态表单 属性用法 ElPlusTable 同样支持官方 ElementPlus Table 的大部分属性,在属性配置项中,使用 tableAttr: { xxx: 'xxx' } 的方式

代码示例
ts
const tableConfig = ref({
  tableAttr: { stripe: true }, 
  column: [
    { prop: 'name', label: '名字' },
    { prop: 'sex', label: '性别', format: 'formatSex' },
    { prop: 'age', label: '年龄' },
    { prop: 'address', label: '地址' }
  ]
} as ITableConfig)
const tableConfig = ref({
  tableAttr: { stripe: true }, 
  column: [
    { prop: 'name', label: '名字' },
    { prop: 'sex', label: '性别', format: 'formatSex' },
    { prop: 'age', label: '年龄' },
    { prop: 'address', label: '地址' }
  ]
} as ITableConfig)

这里就不做多的介绍,主要演示 content 的特殊用法

代码示例
vue
<ElPlusTable ref="tableListRef" v-model="tableData" :tableConfig="tableConfig" :isPager="false" />

<script lang="ts" setup>
const tableConfig = ref({
  column: [
    { prop: 'name', label: '名字' },
    { prop: 'sex', label: '性别', format: 'formatSex' },
    {
      prop: 'age',
      label: '年龄',
      content: (data: any, formData: any) => {
        return data > 50 ? '这个年龄大于50' : ''
      }
    },
    { prop: 'address', label: '地址' }
  ]
} as ITableConfig)
</script>
<ElPlusTable ref="tableListRef" v-model="tableData" :tableConfig="tableConfig" :isPager="false" />

<script lang="ts" setup>
const tableConfig = ref({
  column: [
    { prop: 'name', label: '名字' },
    { prop: 'sex', label: '性别', format: 'formatSex' },
    {
      prop: 'age',
      label: '年龄',
      content: (data: any, formData: any) => {
        return data > 50 ? '这个年龄大于50' : ''
      }
    },
    { prop: 'address', label: '地址' }
  ]
} as ITableConfig)
</script>

远程数据拉取

配置 fetch: (data) => Promise 属性获取远程数据进行渲染

代码示例
vue
<ElPlusTable ref="tableListRef" :tableConfig="tableConfig" :isPager="false" />

<script lang="ts" setup>
const tableConfig = ref({
  fetch: async (postData: any) => {
    const result = { records: tableData }
    return await new Promise((resolve) => {
      setTimeout(() => resolve(result), 1000)
    })
  },
  column: [
    { prop: 'name', label: '名字' },
    { prop: 'sex', label: '性别', format: 'formatSex' },
    { prop: 'age', label: '年龄' },
    { prop: 'address', label: '地址' }
  ]
} as ITableConfig)
</script>
<ElPlusTable ref="tableListRef" :tableConfig="tableConfig" :isPager="false" />

<script lang="ts" setup>
const tableConfig = ref({
  fetch: async (postData: any) => {
    const result = { records: tableData }
    return await new Promise((resolve) => {
      setTimeout(() => resolve(result), 1000)
    })
  },
  column: [
    { prop: 'name', label: '名字' },
    { prop: 'sex', label: '性别', format: 'formatSex' },
    { prop: 'age', label: '年龄' },
    { prop: 'address', label: '地址' }
  ]
} as ITableConfig)
</script>

也可以直接引用 api 使用方法

ts
import { queryPage } from '@/api/xxx'

const tableConfig = ref({
  fetch: queryPage
  //...
} as ITableConfig)
import { queryPage } from '@/api/xxx'

const tableConfig = ref({
  fetch: queryPage
  //...
} as ITableConfig)

TIP

注意: tableConfig 中定义了 fetch 属性,就不要再添加 v-model 绑定了,会出现性能问题,如果实在需要获取 table 中 fetch 的结果数据,请自行添加 inited 回调钩子!!!请悉知!

代码示例
vue

<ElPlusTable ref="tableListRef" v-model="tableData" :tableConfig="tableConfig" :isPager="false" /> 
<ElPlusTable ref="tableListRef" @inited="tableData" :tableConfig="tableConfig" :isPager="false" />

<script lang="ts" setup>
  const tableConfig = ref({
    fetch: (postData: any) => new Promise()
    //...
  } as ITableConfig)
  // 返回fetch 的结果数据
  function tableData(data: any) {} 
</script>

<ElPlusTable ref="tableListRef" v-model="tableData" :tableConfig="tableConfig" :isPager="false" /> 
<ElPlusTable ref="tableListRef" @inited="tableData" :tableConfig="tableConfig" :isPager="false" />

<script lang="ts" setup>
  const tableConfig = ref({
    fetch: (postData: any) => new Promise()
    //...
  } as ITableConfig)
  // 返回fetch 的结果数据
  function tableData(data: any) {} 
</script>

分页表格

使用分页的前提,是从 fetch 调用接口获取数据,并配置 isPager: boolean 属性,来控制表格是否分页,默认为 true,配置 pageSize: number 属性来控制每页显示条数

代码示例
vue
<ElPlusTable ref="tableListRef" v-bind="tableConfig" />

<script lang="ts" setup>
const tableConfig = ref({
  pageSize: 2,
  tableConfig: {
    fetch: async (postData: any) => {
      const result = { total: tableData.length, records: tableData.filter((item: any, i: number) => (postData.current - 1) * postData.size <= i && i <= postData.current * postData.size - 1), current: postData.current } // (current-1)*size<=i<=(current*size)-1
      return await new Promise((resolve) => {
        setTimeout(() => resolve(result), 1000)
      })
    },
    column: [
      { prop: 'name', label: '名字' },
      { prop: 'sex', label: '性别', format: 'formatSex' },
      { prop: 'age', label: '年龄' },
      { prop: 'address', label: '地址' }
    ]
  }
})
</script>
<ElPlusTable ref="tableListRef" v-bind="tableConfig" />

<script lang="ts" setup>
const tableConfig = ref({
  pageSize: 2,
  tableConfig: {
    fetch: async (postData: any) => {
      const result = { total: tableData.length, records: tableData.filter((item: any, i: number) => (postData.current - 1) * postData.size <= i && i <= postData.current * postData.size - 1), current: postData.current } // (current-1)*size<=i<=(current*size)-1
      return await new Promise((resolve) => {
        setTimeout(() => resolve(result), 1000)
      })
    },
    column: [
      { prop: 'name', label: '名字' },
      { prop: 'sex', label: '性别', format: 'formatSex' },
      { prop: 'age', label: '年龄' },
      { prop: 'address', label: '地址' }
    ]
  }
})
</script>

合并行/列

需要在列表配置 isColSpan: boolean / isRowSpan: boolean 属性。哪一项需要合并列,就给它配置 isRowSpan: true;如果要合并行,就需要给要合并的列表项都配置 isColSpan: true

注意: 这里的合并,是把相同并且相邻的数据进行自动合并

代码示例
vue
<ElPlusTable ref="tableListRef" v-model="tableData" v-bind="tableConfig" :isPager="false" />

<script lang="ts" setup>
let tableData = reactive([
  { id: 1, name: '商品1', price: 10, sellPrice: 15, number: 10 },
  { id: 2, name: '商品1', price: 25.2, sellPrice: 25.2, number: 2 },
  { id: 3, name: '商品2', price: 25.2, sellPrice: 26, number: 12 },
  { id: 4, name: '商品1', price: 25.2, sellPrice: 28, number: 8 },
  { id: 5, name: '商品3', price: 2, sellPrice: 2, number: 6 }
])
const tableConfig = ref({
  tableConfig: {
    column: [
      { prop: 'id', label: 'id', minWidth: '120px' },
      { prop: 'name', label: '商品名称', minWidth: '120px', isRowSpan: true, align: 'center' },
      { prop: 'price', label: '价格', minWidth: '120px', format: 'yuan', isColSpan: true, align: 'center' },
      { prop: 'sellPrice', label: '销售价格', format: 'yuan', minWidth: '120px', isColSpan: true },
      { prop: 'number', label: '商品数量', minWidth: '120px' }
    ]
  }
})
</script>
<ElPlusTable ref="tableListRef" v-model="tableData" v-bind="tableConfig" :isPager="false" />

<script lang="ts" setup>
let tableData = reactive([
  { id: 1, name: '商品1', price: 10, sellPrice: 15, number: 10 },
  { id: 2, name: '商品1', price: 25.2, sellPrice: 25.2, number: 2 },
  { id: 3, name: '商品2', price: 25.2, sellPrice: 26, number: 12 },
  { id: 4, name: '商品1', price: 25.2, sellPrice: 28, number: 8 },
  { id: 5, name: '商品3', price: 2, sellPrice: 2, number: 6 }
])
const tableConfig = ref({
  tableConfig: {
    column: [
      { prop: 'id', label: 'id', minWidth: '120px' },
      { prop: 'name', label: '商品名称', minWidth: '120px', isRowSpan: true, align: 'center' },
      { prop: 'price', label: '价格', minWidth: '120px', format: 'yuan', isColSpan: true, align: 'center' },
      { prop: 'sellPrice', label: '销售价格', format: 'yuan', minWidth: '120px', isColSpan: true },
      { prop: 'number', label: '商品数量', minWidth: '120px' }
    ]
  }
})
</script>

TIP

目前 Table 表格还不能支持配置 span-method 属性,请悉知!

合计行数据

summaryConf 里配置 prop: stringlabel: string可实现该列表的金额合计数据

代码示例
html
<ElPlusTable ref="tableListRef" v-model="tableData" v-bind="tableConfig" :isPager="false" />

<script lang="ts" setup>
  const tableConfig = ref({
    tableConfig: {
      summaryConf: {
        prop: 'price',
        label: '价格总计'
      },
      column: [
        { prop: 'id', label: 'id', minWidth: '120px' },
        { prop: 'name', label: '商品名称', minWidth: '120px', isRowSpan: true, align: 'center' },
        { prop: 'price', label: '价格', minWidth: '120px', format: 'yuan', isColSpan: true, align: 'center' },
        { prop: 'sellPrice', label: '销售价格', format: 'yuan', minWidth: '120px', isColSpan: true },
        { prop: 'number', label: '商品数量', minWidth: '120px' }
      ]
    }
  })
</script>
<ElPlusTable ref="tableListRef" v-model="tableData" v-bind="tableConfig" :isPager="false" />

<script lang="ts" setup>
  const tableConfig = ref({
    tableConfig: {
      summaryConf: {
        prop: 'price',
        label: '价格总计'
      },
      column: [
        { prop: 'id', label: 'id', minWidth: '120px' },
        { prop: 'name', label: '商品名称', minWidth: '120px', isRowSpan: true, align: 'center' },
        { prop: 'price', label: '价格', minWidth: '120px', format: 'yuan', isColSpan: true, align: 'center' },
        { prop: 'sellPrice', label: '销售价格', format: 'yuan', minWidth: '120px', isColSpan: true },
        { prop: 'number', label: '商品数量', minWidth: '120px' }
      ]
    }
  })
</script>

添加 sumFn: ( tableData: any[ ], allSelectRowList: any[ ] ) => string 自定义合计方法

代码示例
html
<div class="demo">
  <ElPlusTable ref="tableListRef" v-model="tableData" v-bind="table1Config" :isPager="false" />
</div>
<div class="demo">
  <ElPlusTable ref="tableListRef" v-model="tableData" v-bind="table2Config" :isPager="false" />
</div>

<script lang="ts" setup>
  import { inject } from 'vue'
  const format = inject('format' as any)
  const table1Config = ref({
    tableConfig: {
      summaryConf: {
        prop: 'sellPrice',
        label: '总销售价格',
        sumFn: (tableData: any[]) => {
          return format.yuan(
            tableData.reduce((total: number, current: any) => {
              return (total += current.sellPrice * current.number)
            }, 0)
          )
        }
      },
      column: [
        { prop: 'id', label: 'id', minWidth: '120px' },
        { prop: 'name', label: '商品名称', minWidth: '120px', isRowSpan: true, align: 'center' },
        { prop: 'price', label: '价格', minWidth: '120px', format: 'yuan', isColSpan: true, align: 'center' },
        { prop: 'sellPrice', label: '销售价格', format: 'yuan', minWidth: '120px', isColSpan: true },
        { prop: 'number', label: '商品数量', minWidth: '120px' }
      ]
    }
  })

  const table2Config = ref({
    type: 'selection',
    tableConfig: {
      summaryConf: {
        prop: 'sellPrice',
        label: '总销售价格',
        sumFn: (tableData: any[], allSelectRowList: any[]) => {
          return format.yuan(
            allSelectRowList.reduce((total: number, current: any) => {
              return (total += current.sellPrice * current.number)
            }, 0)
          )
        }
      },
      column: [
        { prop: 'id', label: 'id', minWidth: '120px' },
        { prop: 'name', label: '商品名称', minWidth: '120px', isRowSpan: true, align: 'center' },
        { prop: 'price', label: '价格', minWidth: '120px', format: 'yuan', isColSpan: true, align: 'center' },
        { prop: 'sellPrice', label: '销售价格', format: 'yuan', minWidth: '120px', isColSpan: true },
        { prop: 'number', label: '商品数量', minWidth: '120px' }
      ]
    }
  })
</script>
<div class="demo">
  <ElPlusTable ref="tableListRef" v-model="tableData" v-bind="table1Config" :isPager="false" />
</div>
<div class="demo">
  <ElPlusTable ref="tableListRef" v-model="tableData" v-bind="table2Config" :isPager="false" />
</div>

<script lang="ts" setup>
  import { inject } from 'vue'
  const format = inject('format' as any)
  const table1Config = ref({
    tableConfig: {
      summaryConf: {
        prop: 'sellPrice',
        label: '总销售价格',
        sumFn: (tableData: any[]) => {
          return format.yuan(
            tableData.reduce((total: number, current: any) => {
              return (total += current.sellPrice * current.number)
            }, 0)
          )
        }
      },
      column: [
        { prop: 'id', label: 'id', minWidth: '120px' },
        { prop: 'name', label: '商品名称', minWidth: '120px', isRowSpan: true, align: 'center' },
        { prop: 'price', label: '价格', minWidth: '120px', format: 'yuan', isColSpan: true, align: 'center' },
        { prop: 'sellPrice', label: '销售价格', format: 'yuan', minWidth: '120px', isColSpan: true },
        { prop: 'number', label: '商品数量', minWidth: '120px' }
      ]
    }
  })

  const table2Config = ref({
    type: 'selection',
    tableConfig: {
      summaryConf: {
        prop: 'sellPrice',
        label: '总销售价格',
        sumFn: (tableData: any[], allSelectRowList: any[]) => {
          return format.yuan(
            allSelectRowList.reduce((total: number, current: any) => {
              return (total += current.sellPrice * current.number)
            }, 0)
          )
        }
      },
      column: [
        { prop: 'id', label: 'id', minWidth: '120px' },
        { prop: 'name', label: '商品名称', minWidth: '120px', isRowSpan: true, align: 'center' },
        { prop: 'price', label: '价格', minWidth: '120px', format: 'yuan', isColSpan: true, align: 'center' },
        { prop: 'sellPrice', label: '销售价格', format: 'yuan', minWidth: '120px', isColSpan: true },
        { prop: 'number', label: '商品数量', minWidth: '120px' }
      ]
    }
  })
</script>