Table 表格

Table 组件需要配合 Column 组件使用。

示例

尺寸、样式

可选的 ui 尺寸属性值:slim/alt/bordered

ID
Name
Bid
Last updated
Operations
3154
Steve Rogers
¥1024.00
2013-11-17
3155
Thor Odinson
¥598.00
2014-02-14
3156
Tony Stark
¥820.00
2017-06-10
3157
Stephen Strange
¥736.00
2018-01-09
<template>
<article>
  <section>
    <veui-checkbox v-model="slim">
      Slim
    </veui-checkbox>
    <veui-checkbox v-model="alt">
      Alternative
    </veui-checkbox>
    <veui-checkbox v-model="bordered">
      Bordered
    </veui-checkbox>
  </section>
  <section>
    <veui-table
      :ui="ui"
      :data="data"
      key-field="id"
    >
      <veui-table-column
        field="id"
        title="ID"
      />
      <veui-table-column
        field="name"
        title="Name"
      />
      <veui-table-column
        field="bid"
        title="Bid"
        width="160"
        align="right"
      >
        <template slot-scope="{ bid }">
          {{ bid | currency }}
        </template>
      </veui-table-column>
      <veui-table-column
        field="updateDate"
        title="Last updated"
        align="center"
      >
        <template slot-scope="{ updateDate }"></template>
      </veui-table-column>
      <veui-table-column
        field="operation"
        title="Operations"
      >
        <template slot-scope="{ index }">
          <veui-button
            ui="link alert"
            @click="remove(index)"
          >
            Remove
          </veui-button>
        </template>
      </veui-table-column>
    </veui-table>
  </section>
</article>
</template>

<script>
import { Checkbox, Table, Column, Button } from 'veui'

export default {
  components: {
    'veui-table': Table,
    'veui-table-column': Column,
    'veui-checkbox': Checkbox,
    'veui-button': Button
  },
  filters: {
    currency (value) {
      return '¥' + value.toFixed(2)
    },
    date (value) {
      let [, ...parts] = value.match(/(\d{4})(\d{2})(\d{2})/) || []
      return parts.join('-')
    }
  },
  data () {
    return {
      slim: false,
      alt: false,
      bordered: false,
      data: [
        {
          id: '3154',
          name: 'Steve Rogers',
          bid: 1024,
          updateDate: '20131117'
        },
        {
          id: '3155',
          name: 'Thor Odinson',
          bid: 598,
          updateDate: '20140214'
        },
        {
          id: '3156',
          name: 'Tony Stark',
          bid: 820,
          updateDate: '20170610'
        },
        {
          id: '3157',
          name: 'Stephen Strange',
          bid: 736,
          updateDate: '20180109'
        }
      ]
    }
  },
  computed: {
    ui () {
      return [
        ...(this.slim ? ['slim'] : []),
        ...(this.bordered ? ['bordered'] : []),
        ...(this.alt ? ['alt'] : [])
      ].join(' ')
    }
  },
  methods: {
    remove (index) {
      this.data.splice(index, 1)
    }
  }
}
</script>

<style lang="less" scoped>
section {
  margin-bottom: 20px;
}

.veui-checkbox {
  margin-right: 20px;
}
</style>

高级

允许自定义唯一键、设定选择模式以及进行排序。

ID
Group
Name
Bid
Last updated
Opertaions
3154
1577
Steve Rogers
¥1024.00
2013-11-17
3155
Thor Odinson
¥598.00
2014-02-14
3156
1578
Tony Stark
¥820.00
2017-06-10
3157
Stephen Strange
¥736.00
2018-01-09

Selected: ["1577"]

<template>
<article>
  <section>
    <veui-button
      ui="primary"
      @click="append"
    >
      Add
    </veui-button>
  </section>
  <section>
    <veui-checkbox
      v-model="mode"
      true-value="multiple"
      false-value="single"
    >
      Multiple selection
    </veui-checkbox>
    <veui-checkbox v-model="showOps">
      Display “Operations”
    </veui-checkbox>
    <veui-checkbox v-model="selectSpanRow">
      Select by “Group” <small>(instead of “ID”)</small>
    </veui-checkbox>
  </section>
  <section>
    <veui-table
      ui="alt bordered"
      :data="data"
      :key-field="selectSpanRow ? 'group' : 'id'"
      selectable
      :select-mode="mode"
      :order-by="orderBy"
      :order="order"
      :selected.sync="selected"
      @sort="handleSort"
    >
      <veui-table-column
        field="id"
        title="ID"
        sortable
      >
        <template slot="head">
          <strong>ID</strong>
        </template>
        <template slot="foot">
          <strong>Total</strong>
        </template>
      </veui-table-column>
      <veui-table-column
        field="group"
        title="Group"
        :span="groupSpan"
      />
      <veui-table-column
        field="name"
        title="Name"
        width="160"
      />
      <veui-table-column
        field="bid"
        title="Bid"
        sortable
        width="160"
        align="right"
      >
        <template slot-scope="{ bid }"></template>
        <template slot="foot">
          <strong>{{ total | currency }}</strong>
        </template>
      </veui-table-column>
      <veui-table-column
        field="updateDate"
        title="Last updated"
        align="center"
      >
        <template slot-scope="{ id, updateDate }">
          <span :ref="`time-a-${id}`">{{ updateDate | date }}</span>
          <veui-tooltip :target="`time-a-${id}`">
            {{ updateDate | time }}
          </veui-tooltip>
        </template>
      </veui-table-column>
      <veui-table-column
        v-if="showOps"
        field="operation"
        title="Opertaions"
      >
        <template slot-scope="{ index }">
          <veui-button
            ui="link alert"
            @click="del(index)"
          >
            Remove
          </veui-button>
        </template>
      </veui-table-column>
    </veui-table>
    <p>Selected: {{ JSON.stringify(selected) }}</p>
  </section>
</article>
</template>

<script>
import { groupBy } from 'lodash'
import { Button, Checkbox, Table, Column, Tooltip } from 'veui'

export default {
  components: {
    'veui-button': Button,
    'veui-table': Table,
    'veui-table-column': Column,
    'veui-tooltip': Tooltip,
    'veui-checkbox': Checkbox
  },
  filters: {
    currency (value) {
      return '¥' + value.toFixed(2)
    },
    date (value) {
      let [, ...parts] = value.match(/(\d{4})(\d{2})(\d{2})/) || []
      return parts.join('-')
    },
    time (value) {
      let [, ...parts] = value.match(/(\d{4})(\d{2})(\d{2})/) || []
      return parts.join('-') + ' 00:00:00'
    }
  },
  data () {
    return {
      mode: 'multiple',
      showOps: true,
      selectSpanRow: true,
      data: [
        {
          id: '3154',
          name: 'Steve Rogers',
          bid: 1024,
          updateDate: '20131117',
          group: '1577'
        },
        {
          id: '3155',
          name: 'Thor Odinson',
          bid: 598,
          updateDate: '20140214',
          group: '1577'
        },
        {
          id: '3156',
          name: 'Tony Stark',
          bid: 820,
          updateDate: '20170610',
          group: '1578'
        },
        {
          id: '3157',
          name: 'Stephen Strange',
          bid: 736,
          updateDate: '20180109',
          group: '1578'
        }
      ],
      nextId: 3158,
      nextIndex: 4,
      order: false,
      orderBy: null,
      selected: ['1577'],
      groupSpan: i => {
        let groups = groupBy(this.data, 'group')
        let item = this.data[i]
        let itemGroup = groups[item.group]
        if (item.id === (itemGroup[0] || {}).id) {
          return {
            row: itemGroup.length
          }
        }
        return {
          row: 0
        }
      }
    }
  },
  computed: {
    total () {
      return this.data.reduce((total, item) => {
        return total + item.bid
      }, 0)
    }
  },
  methods: {
    del (index) {
      this.data.splice(index, 1)
    },
    append () {
      let d = new Date(Date.now() + Math.floor(Math.random() * 1e10))

      let item = {
        id: String(this.nextId),
        group: String(Math.floor(this.nextId / 2)),
        name: `Character-${this.nextIndex}`,
        bid: Math.floor(Math.random() * 1280),
        updateDate:
          d.getFullYear() +
          String(d.getMonth() + 1).padStart(2, '0') +
          String(d.getMonth() + 1).padStart(2, '0')
      }
      this.nextId++
      this.nextIndex++
      this.data.push(item)
    },
    handleSort (orderBy, order) {
      this.orderBy = orderBy
      this.order = order
    }
  }
}
</script>

<style lang="less" scoped>
section {
  margin-bottom: 20px;
}

.veui-checkbox {
  margin-right: 20px;
}
</style>

内部滚动模式

允许启用内部滚动模式,以达到固定表头表底的效果。

3154
Steve Rogers
¥1024.00
2013-11-17
3155
Thor Odinson
¥598.00
2014-02-14
3156
Tony Stark
¥820.00
2017-06-10
3157
Stephen Strange
¥736.00
2018-01-09
3158
Natalie Romanoff
¥736.00
2018-01-23
3159
Bruce Banner
¥736.00
2018-12-01
3160
Peter Parker
¥736.00
2018-11-13
3161
T'Challa
¥736.00
2018-07-30
3162
Loki
¥736.00
2018-06-01
<template>
<article>
  <section>
    <veui-table
      :data="data"
      scroll="360"
      key-field="id"
    >
      <veui-table-column
        field="id"
        title="ID"
      />
      <veui-table-column
        field="name"
        title="Name"
      />
      <veui-table-column
        field="bid"
        title="Bid"
        width="160"
        align="right"
      >
        <template slot-scope="{ bid }">
          {{ bid | currency }}
        </template>
      </veui-table-column>
      <veui-table-column
        field="updateDate"
        title="Last updated"
        align="center"
      >
        <template slot-scope="{ updateDate }"></template>
      </veui-table-column>
    </veui-table>
  </section>
</article>
</template>

<script>
import { Table, Column } from 'veui'

export default {
  components: {
    'veui-table': Table,
    'veui-table-column': Column
  },
  filters: {
    currency (value) {
      return '¥' + value.toFixed(2)
    },
    date (value) {
      let [, ...parts] = value.match(/(\d{4})(\d{2})(\d{2})/) || []
      return parts.join('-')
    }
  },
  data () {
    return {
      data: [
        {
          id: '3154',
          name: 'Steve Rogers',
          bid: 1024,
          updateDate: '20131117'
        },
        {
          id: '3155',
          name: 'Thor Odinson',
          bid: 598,
          updateDate: '20140214'
        },
        {
          id: '3156',
          name: 'Tony Stark',
          bid: 820,
          updateDate: '20170610'
        },
        {
          id: '3157',
          name: 'Stephen Strange',
          bid: 736,
          updateDate: '20180109'
        },
        {
          id: '3158',
          name: 'Natalie Romanoff',
          bid: 736,
          updateDate: '20180123'
        },
        {
          id: '3159',
          name: 'Bruce Banner',
          bid: 736,
          updateDate: '20181201'
        },
        {
          id: '3160',
          name: 'Peter Parker',
          bid: 736,
          updateDate: '20181113'
        },
        {
          id: '3161',
          name: "T'Challa",
          bid: 736,
          updateDate: '20180730'
        },
        {
          id: '3162',
          name: 'Loki',
          bid: 736,
          updateDate: '20180601'
        }
      ]
    }
  }
}
</script>

<style lang="less" scoped>
section {
  margin-bottom: 20px;
}
</style>

展开行

支持将带有子数据的行进行展开。

ID
Name
Bid
Last updated
3154
Steve Rogers
¥1024.00
2013-11-17
3155
Thor Odinson
¥598.00
2014-02-14
3156
Tony Stark
¥820.00
2017-06-10
3157
Stephen Strange
¥736.00
2018-01-09
<template>
<article>
  <section>
    <veui-table
      :data="data"
      expandable
      key-field="id"
    >
      <veui-table-column
        field="id"
        title="ID"
      />
      <veui-table-column
        field="name"
        title="Name"
      />
      <veui-table-column
        field="bid"
        title="Bid"
        width="160"
        align="right"
      >
        <template slot-scope="{ bid }">
          {{ bid | currency }}
        </template>
      </veui-table-column>
      <veui-table-column
        field="updateDate"
        title="Last updated"
        align="center"
      >
        <template slot-scope="{ updateDate }"></template>
      </veui-table-column>
    </veui-table>
  </section>
</article>
</template>

<script>
import { Table, Column } from 'veui'

export default {
  components: {
    'veui-table': Table,
    'veui-table-column': Column
  },
  filters: {
    currency (value) {
      return '¥' + value.toFixed(2)
    },
    date (value) {
      let [, ...parts] = value.match(/(\d{4})(\d{2})(\d{2})/) || []
      return parts.join('-')
    }
  },
  data () {
    return {
      data: [
        {
          id: '3154',
          name: 'Steve Rogers',
          bid: 1024,
          updateDate: '20131117',
          children: [
            {
              id: '3154',
              name: 'Steve Rogers',
              bid: 1024,
              updateDate: '20131117'
            },
            {
              id: '3154',
              name: 'Steve Rogers',
              bid: 1001,
              updateDate: '20131116'
            },
            {
              id: '3154',
              name: 'Steve Rogers',
              bid: 985,
              updateDate: '20131115'
            }
          ]
        },
        {
          id: '3155',
          name: 'Thor Odinson',
          bid: 598,
          updateDate: '20140214',
          children: [
            {
              id: '3155',
              name: 'Thor Odinson',
              bid: 520,
              updateDate: '20131116'
            }
          ]
        },
        {
          id: '3156',
          name: 'Tony Stark',
          bid: 820,
          updateDate: '20170610',
          children: [
            {
              id: '3156',
              name: 'Tony Stark',
              bid: 800,
              updateDate: '20131116'
            },
            { id: '3156', name: 'Tony Stark', bid: 763, updateDate: '20131115' }
          ]
        },
        {
          id: '3157',
          name: 'Stephen Strange',
          bid: 736,
          updateDate: '20180109',
          children: [
            {
              id: '3157',
              name: 'Stephen Strange',
              bid: 704,
              updateDate: '20131116'
            },
            {
              id: '3157',
              name: 'Stephen Strange',
              bid: 666,
              updateDate: '20131112'
            },
            {
              id: '3157',
              name: 'Stephen Strange',
              bid: 521,
              updateDate: '20131111'
            },
            {
              id: '3157',
              name: 'Stephen Strange',
              bid: 428,
              updateDate: '20131110'
            }
          ]
        }
      ]
    }
  }
}
</script>

<style lang="less" scoped>
section {
  margin-bottom: 20px;
}
</style>

API

属性

名称类型默认值描述
uistring=-

预设样式。

描述
alt备选样式。
bordered单元格带分隔边框的样式。
slim紧凑样式。
dataArray<Object>-表格数据。
key-fieldstring-用于指定充当表格数据的键的列标志符。值对应 data 属性中数据项的某个字段名称。对应字段的值则会作为行元素的 key 属性输出。当 selectable 属性为 true 时,也可以用来指定在存在纵向合并单元格的情况下以哪一列的不同行作为选择项,此时值必须来自内部某个 Column 组件的 field 属性。
selectablebooleanfalse是否支持表格行的选择。
select-modestring'multiple'选择模式,支持的值为 single/multiple,分别对应于单选/多选模式。
selectedArray<*>|*[]

.sync

已选行。当 select-mode'multiple' 时为已选行 key-field 对应字段值的数组;为 'single' 时为已选行 key-field 对应字段值。

expandablebooleanfalse是否允许展开行。
expandedArray<*>[]

.sync

已展开行。为已展开行 key-field 对应字段值的数组。

orderstring|booleanfalse排序顺序。为 false 时表示无序,为字符串值 'asc'/'desc' 时分别为升序/降序。
order-bystring-用于指定当前基于哪一列进行了排序,值必须来自内部某个 Column 组件的 field 属性。
scrollnumber-指定滚动区域的最大高度,当超出此高度时,表格将进入固定表头和底部只允许数据区域滚动的模式。

插槽

名称描述
default用于定义表格列,只能包含 Column 组件。
no-data用于定义无数据时要展现的内容。
foot表格脚部内容,整个区域将打通成为一个容器,不再保留分列。
sub-row

展开行后子行的内容。使用此插槽时,内容会作为行展开下方通栏显式的子行内容。使用此插槽时会覆盖 Column 的作用域插槽 sub-row 内容。

作用域参数为 data 内当前行数据中的所有字段,以及当前行对应索引值 index

事件

名称描述
select

切换已选项时触发。回调参数为 (selected, item, selectedItems)

名称类型描述
selectedbooleantrue 表示已选择,false 则表示取消选择。
itemObject选择状态发生变化的 data 属性中的数据项。当存在纵向合并单元格且以相应行作为键进行选择时,将返回第一条相关的 data 数据项。
selectedItemsObject<string, Object|Array>当前所有已选项的信息,键为 key-field 对应字段,值为对应的 data 数据项。当存在纵向合并单元格且以相应行作为键进行选择时,值为所有相关行数据项组成的数组。
sort

进行排序时触发的事件。回调参数为 (field, order)

名称类型描述
fieldstring基于哪一列进行排序。值来自对应 Column 组件的 field 属性。
orderstring|booleanorder 属性