Table
Basic Usage
| 1 | Li Xiaoying | 522 | 4 | |
| 15 | Du Xiaohao | 462 | 18 | |
| 18 | Tang Xiaoqing | 482 | 12 | |
| 28 | Tian Xiaofeng | 475 | 15 | |
| 35 | Wu Xiaohao | 372 | 41 | |
| 41 | Wu Xiaoke | 404 | 33 | |
| 46 | Mu Xiaoyi | 409 | 40 | |
| 43 | Zou Xiaohui | 293 | 53 |
vue
<template>
<bp-table
:data="list"
border
row-key="seat"
:row-selection="rowSelection"
v-model:selectedKeys="selectedKeys"
v-model:selectedKey="selectedKey"
>
<template #columns>
<bp-table-column title="Seat" data-index="seat" :width="100">
<template #cell="{ record }">
<span style="font-weight: bold">{{ record.seat }}</span>
</template>
</bp-table-column>
<bp-table-column title="Name" data-index="name" align="center" />
<bp-table-column title="Score" data-index="results" :width="100" />
<bp-table-column title="Class rank" data-index="ranking" :width="100" />
</template>
</bp-table>
</template>
<script setup lang="ts">
import { ref } from "vue";
const list = [
{ seat: "1", name: "Li Xiaoying", results: "522", ranking: "4" },
{ seat: "15", name: "Du Xiaohao", results: "462", ranking: "18" },
{ seat: "18", name: "Tang Xiaoqing", results: "482", ranking: "12" },
{ seat: "28", name: "Tian Xiaofeng", results: "475", ranking: "15" },
{ seat: "35", name: "Wu Xiaohao", results: "372", ranking: "41" },
{ seat: "41", name: "Wu Xiaoke", results: "404", ranking: "33" },
{ seat: "46", name: "Mu Xiaoyi", results: "409", ranking: "40" },
{ seat: "43", name: "Zou Xiaohui", results: "293", ranking: "53" },
];
const selectedKey = ref("");
const selectedKeys = ref([]);
const rowSelection = {
type: "radio",
// type: "checkbox",
};
</script>Header scroll sync test
Test header/body scroll sync and column alignment
Fixed column widths + horizontal scroll (container 600px, table ~1000px)
| 1 | Zhang San | 28 | Beijing | Frontend Engineer | zhangsan@example.com | Active | |
| 2 | Li Si | 32 | Shanghai | Backend Engineer | lisi@example.com | Active | |
| 3 | Wang Wu | 26 | Shenzhen | UI Designer | wangwu@example.com | Resigned | |
| 4 | Zhao Liu | 30 | Guangzhou | Product Manager | zhaoliu@example.com | Active |
Fixed columns (ID fixed left, Status fixed right)
| 1 | Zhang San | 28 | Beijing | Frontend Engineer | zhangsan@example.com | 13800138001 | Active |
| 2 | Li Si | 32 | Shanghai | Backend Engineer | lisi@example.com | 13800138002 | Active |
| 3 | Wang Wu | 26 | Shenzhen | UI Designer | wangwu@example.com | 13800138003 | Resigned |
| 4 | Zhao Liu | 30 | Guangzhou | Product Manager | zhaoliu@example.com | 13800138004 | Active |
| 5 | User 5 | 25 | Beijing | Software Engineer | user5@example.com | 138001380005 | Resigned |
| 6 | User 6 | 26 | Shanghai | Designer | user6@example.com | 138001380006 | Active |
| 7 | User 7 | 27 | Shenzhen | Product Manager | user7@example.com | 138001380007 | Active |
| 8 | User 8 | 28 | Guangzhou | QA Engineer | user8@example.com | 138001380008 | Resigned |
| 9 | User 9 | 29 | Hangzhou | Operations | user9@example.com | 138001380009 | Active |
| 10 | User 10 | 30 | Beijing | Software Engineer | user10@example.com | 138001380010 | Active |
| 11 | User 11 | 31 | Shanghai | Designer | user11@example.com | 138001380011 | Resigned |
| 12 | User 12 | 32 | Shenzhen | Product Manager | user12@example.com | 138001380012 | Active |
| 13 | User 13 | 33 | Guangzhou | QA Engineer | user13@example.com | 138001380013 | Active |
| 14 | User 14 | 34 | Hangzhou | Operations | user14@example.com | 138001380014 | Resigned |
| 15 | User 15 | 25 | Beijing | Software Engineer | user15@example.com | 138001380015 | Active |
| 16 | User 16 | 26 | Shanghai | Designer | user16@example.com | 138001380016 | Active |
| 17 | User 17 | 27 | Shenzhen | Product Manager | user17@example.com | 138001380017 | Resigned |
| 18 | User 18 | 28 | Guangzhou | QA Engineer | user18@example.com | 138001380018 | Active |
| 19 | User 19 | 29 | Hangzhou | Operations | user19@example.com | 138001380019 | Active |
| 20 | User 20 | 30 | Beijing | Software Engineer | user20@example.com | 138001380020 | Resigned |
| 21 | User 21 | 31 | Shanghai | Designer | user21@example.com | 138001380021 | Active |
| 22 | User 22 | 32 | Shenzhen | Product Manager | user22@example.com | 138001380022 | Active |
| 23 | User 23 | 33 | Guangzhou | QA Engineer | user23@example.com | 138001380023 | Resigned |
| 24 | User 24 | 34 | Hangzhou | Operations | user24@example.com | 138001380024 | Active |
Mixed widths (some fixed + flexible)
| 1 | Zhang San | 28 | Beijing | Frontend Engineer | zhangsan@example.com | Active |
| 2 | Li Si | 32 | Shanghai | Backend Engineer | lisi@example.com | Active |
| 3 | Wang Wu | 26 | Shenzhen | UI Designer | wangwu@example.com | Resigned |
| 4 | Zhao Liu | 30 | Guangzhou | Product Manager | zhaoliu@example.com | Active |
Vertical + horizontal scroll
| 1 | Zhang San | 28 | Beijing | Frontend Engineer | zhangsan@example.com | 13800138001 | Active | |
| 2 | Li Si | 32 | Shanghai | Backend Engineer | lisi@example.com | 13800138002 | Active | |
| 3 | Wang Wu | 26 | Shenzhen | UI Designer | wangwu@example.com | 13800138003 | Resigned | |
| 4 | Zhao Liu | 30 | Guangzhou | Product Manager | zhaoliu@example.com | 13800138004 | Active | |
| 5 | User 5 | 25 | Beijing | Software Engineer | user5@example.com | 138001380005 | Resigned | |
| 6 | User 6 | 26 | Shanghai | Designer | user6@example.com | 138001380006 | Active | |
| 7 | User 7 | 27 | Shenzhen | Product Manager | user7@example.com | 138001380007 | Active | |
| 8 | User 8 | 28 | Guangzhou | QA Engineer | user8@example.com | 138001380008 | Resigned | |
| 9 | User 9 | 29 | Hangzhou | Operations | user9@example.com | 138001380009 | Active | |
| 10 | User 10 | 30 | Beijing | Software Engineer | user10@example.com | 138001380010 | Active | |
| 11 | User 11 | 31 | Shanghai | Designer | user11@example.com | 138001380011 | Resigned | |
| 12 | User 12 | 32 | Shenzhen | Product Manager | user12@example.com | 138001380012 | Active | |
| 13 | User 13 | 33 | Guangzhou | QA Engineer | user13@example.com | 138001380013 | Active | |
| 14 | User 14 | 34 | Hangzhou | Operations | user14@example.com | 138001380014 | Resigned | |
| 15 | User 15 | 25 | Beijing | Software Engineer | user15@example.com | 138001380015 | Active | |
| 16 | User 16 | 26 | Shanghai | Designer | user16@example.com | 138001380016 | Active | |
| 17 | User 17 | 27 | Shenzhen | Product Manager | user17@example.com | 138001380017 | Resigned | |
| 18 | User 18 | 28 | Guangzhou | QA Engineer | user18@example.com | 138001380018 | Active | |
| 19 | User 19 | 29 | Hangzhou | Operations | user19@example.com | 138001380019 | Active | |
| 20 | User 20 | 30 | Beijing | Software Engineer | user20@example.com | 138001380020 | Resigned | |
| 21 | User 21 | 31 | Shanghai | Designer | user21@example.com | 138001380021 | Active | |
| 22 | User 22 | 32 | Shenzhen | Product Manager | user22@example.com | 138001380022 | Active | |
| 23 | User 23 | 33 | Guangzhou | QA Engineer | user23@example.com | 138001380023 | Resigned | |
| 24 | User 24 | 34 | Hangzhou | Operations | user24@example.com | 138001380024 | Active |
vue
<template>
<div>
<h3>Header scroll sync test</h3>
<p>Test header/body scroll sync and column alignment</p>
<!-- Fixed widths + horizontal scroll -->
<h4>Fixed column widths + horizontal scroll (container 600px, table ~1000px)</h4>
<div style="width: 600px">
<bp-table :data="list" border row-key="id" :scroll="{ x: 1000 }" :row-selection="{ type: 'radio' }">
<template #columns>
<bp-table-column title="ID" data-index="id" :width="80" />
<bp-table-column title="Name" data-index="name" :width="120" />
<bp-table-column title="Age" data-index="age" :width="80" />
<bp-table-column title="City" data-index="city" :width="120" />
<bp-table-column title="Job" data-index="job" :width="200" />
<bp-table-column title="Email" data-index="email" :width="250" />
<bp-table-column title="Status" data-index="status" :width="100" />
</template>
</bp-table>
</div>
<!-- Fixed columns -->
<h4>Fixed columns (ID fixed left, Status fixed right)</h4>
<div style="width: 600px">
<bp-table :data="bigList" border row-key="id" :scroll="{ x: 1100, y: 220 }">
<template #columns>
<bp-table-column title="ID" data-index="id" :width="80" fixed="left" />
<bp-table-column title="Name" data-index="name" :width="120" />
<bp-table-column title="Age" data-index="age" :width="80" />
<bp-table-column title="City" data-index="city" :width="120" />
<bp-table-column title="Job" data-index="job" :width="220" />
<bp-table-column title="Email" data-index="email" :width="260" />
<bp-table-column title="Phone" data-index="phone" :width="140" />
<bp-table-column title="Status" data-index="status" :width="100" fixed="right" />
</template>
</bp-table>
</div>
<!-- Mixed widths -->
<h4>Mixed widths (some fixed + flexible)</h4>
<div style="width: 500px">
<bp-table :data="list" border row-key="id" :scroll="{ x: 800 }">
<template #columns>
<bp-table-column title="ID" data-index="id" :width="60" />
<bp-table-column title="Name" data-index="name" :width="100" />
<bp-table-column title="Age" data-index="age" />
<bp-table-column title="City" data-index="city" />
<bp-table-column title="Job" data-index="job" :width="180" />
<bp-table-column title="Email" data-index="email" :width="220" />
<bp-table-column title="Status" data-index="status" />
</template>
</bp-table>
</div>
<!-- Vertical + horizontal scroll -->
<h4>Vertical + horizontal scroll</h4>
<div style="width: 700px">
<bp-table :data="bigList" border row-key="id" :scroll="{ x: 900, y: 200 }" :row-selection="{ type: 'checkbox' }">
<template #columns>
<bp-table-column title="ID" data-index="id" :width="60" />
<bp-table-column title="Name" data-index="name" :width="100" />
<bp-table-column title="Age" data-index="age" :width="80" />
<bp-table-column title="City" data-index="city" :width="120" />
<bp-table-column title="Job" data-index="job" :width="180" />
<bp-table-column title="Email" data-index="email" :width="200" />
<bp-table-column title="Phone" data-index="phone" :width="120" />
<bp-table-column title="Status" data-index="status" :width="80" />
</template>
</bp-table>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
const list = ref([
{
id: 1,
name: "Zhang San",
age: 28,
city: "Beijing",
job: "Frontend Engineer",
email: "zhangsan@example.com",
phone: "13800138001",
status: "Active",
},
{
id: 2,
name: "Li Si",
age: 32,
city: "Shanghai",
job: "Backend Engineer",
email: "lisi@example.com",
phone: "13800138002",
status: "Active",
},
{
id: 3,
name: "Wang Wu",
age: 26,
city: "Shenzhen",
job: "UI Designer",
email: "wangwu@example.com",
phone: "13800138003",
status: "Resigned",
},
{
id: 4,
name: "Zhao Liu",
age: 30,
city: "Guangzhou",
job: "Product Manager",
email: "zhaoliu@example.com",
phone: "13800138004",
status: "Active",
},
]);
// Extra rows for vertical scroll
const bigList = ref([
...list.value,
...Array.from({ length: 20 }, (_, i) => ({
id: i + 5,
name: `User ${i + 5}`,
age: 25 + (i % 10),
city: ["Beijing", "Shanghai", "Shenzhen", "Guangzhou", "Hangzhou"][i % 5],
job: ["Software Engineer", "Designer", "Product Manager", "QA Engineer", "Operations"][i % 5],
email: `user${i + 5}@example.com`,
phone: `1380013800${(i + 5).toString().padStart(2, "0")}`,
status: i % 3 === 0 ? "Resigned" : "Active",
})),
]);
</script>
<style scoped>
h3,
h4 {
margin: 20px 0 10px 0;
color: #333;
}
p {
margin: 10px 0;
color: #666;
font-size: 14px;
}
.bp-table {
margin-bottom: 30px;
}
div[style*="border"] {
margin-bottom: 20px;
border-radius: 4px;
background-color: #fafafa;
}
</style>Horizontal scroll example
With many columns, the table enables horizontal scroll so each column keeps a proper width
Auto horizontal scroll (unlimited)
| 1 | Zhang San | 28 | Beijing | Frontend Engineer | zhangsan@example.com | 13800138001 | 1 Jianguomenwai Ave, Chaoyang, Beijing | Tech Co., Ltd. | 15000 |
| 2 | Li Si | 32 | Shanghai | Backend Engineer | lisi@example.com | 13800138002 | 100 Century Avenue, Pudong, Shanghai | Internet Company | 18000 |
| 3 | Wang Wu | 26 | Shenzhen | UI Designer | wangwu@example.com | 13800138003 | South Science Park, Nanshan, Shenzhen | Design Studio | 12000 |
| 4 | Zhao Liu | 30 | Guangzhou | Product Manager | zhaoliu@example.com | 13800138004 | Zhujiang New Town, Tianhe, Guangzhou | Startup | 20000 |
Explicit horizontal scroll width (1200px)
| 1 | Zhang San | 28 | Beijing | Frontend Engineer | zhangsan@example.com | 13800138001 | 1 Jianguomenwai Ave, Chaoyang, Beijing | Tech Co., Ltd. | 15000 |
| 2 | Li Si | 32 | Shanghai | Backend Engineer | lisi@example.com | 13800138002 | 100 Century Avenue, Pudong, Shanghai | Internet Company | 18000 |
| 3 | Wang Wu | 26 | Shenzhen | UI Designer | wangwu@example.com | 13800138003 | South Science Park, Nanshan, Shenzhen | Design Studio | 12000 |
| 4 | Zhao Liu | 30 | Guangzhou | Product Manager | zhaoliu@example.com | 13800138004 | Zhujiang New Town, Tianhe, Guangzhou | Startup | 20000 |
Horizontal + vertical scroll
| 1 | Zhang San | 28 | Beijing | Frontend Engineer | zhangsan@example.com | 13800138001 | 1 Jianguomenwai Ave, Chaoyang, Beijing |
| 2 | Li Si | 32 | Shanghai | Backend Engineer | lisi@example.com | 13800138002 | 100 Century Avenue, Pudong, Shanghai |
| 3 | Wang Wu | 26 | Shenzhen | UI Designer | wangwu@example.com | 13800138003 | South Science Park, Nanshan, Shenzhen |
| 4 | Zhao Liu | 30 | Guangzhou | Product Manager | zhaoliu@example.com | 13800138004 | Zhujiang New Town, Tianhe, Guangzhou |
| 5 | User 5 | 25 | Beijing | Software Engineer | user5@example.com | 13800138005 | Address 5 |
| 6 | User 6 | 26 | Shanghai | Designer | user6@example.com | 13800138006 | Address 6 |
| 7 | User 7 | 27 | Shenzhen | Product Manager | user7@example.com | 13800138007 | Address 7 |
| 8 | User 8 | 28 | Guangzhou | QA Engineer | user8@example.com | 13800138008 | Address 8 |
| 9 | User 9 | 29 | Hangzhou | Operations | user9@example.com | 13800138009 | Address 9 |
| 10 | User 10 | 30 | Beijing | Software Engineer | user10@example.com | 138001380010 | Address 10 |
| 11 | User 11 | 31 | Shanghai | Designer | user11@example.com | 138001380011 | Address 11 |
| 12 | User 12 | 32 | Shenzhen | Product Manager | user12@example.com | 138001380012 | Address 12 |
| 13 | User 13 | 33 | Guangzhou | QA Engineer | user13@example.com | 138001380013 | Address 13 |
| 14 | User 14 | 34 | Hangzhou | Operations | user14@example.com | 138001380014 | Address 14 |
| 15 | User 15 | 25 | Beijing | Software Engineer | user15@example.com | 138001380015 | Address 15 |
| 16 | User 16 | 26 | Shanghai | Designer | user16@example.com | 138001380016 | Address 16 |
| 17 | User 17 | 27 | Shenzhen | Product Manager | user17@example.com | 138001380017 | Address 17 |
| 18 | User 18 | 28 | Guangzhou | QA Engineer | user18@example.com | 138001380018 | Address 18 |
| 19 | User 19 | 29 | Hangzhou | Operations | user19@example.com | 138001380019 | Address 19 |
| 20 | User 20 | 30 | Beijing | Software Engineer | user20@example.com | 138001380020 | Address 20 |
| 21 | User 21 | 31 | Shanghai | Designer | user21@example.com | 138001380021 | Address 21 |
| 22 | User 22 | 32 | Shenzhen | Product Manager | user22@example.com | 138001380022 | Address 22 |
| 23 | User 23 | 33 | Guangzhou | QA Engineer | user23@example.com | 138001380023 | Address 23 |
| 24 | User 24 | 34 | Hangzhou | Operations | user24@example.com | 138001380024 | Address 24 |
vue
<template>
<div>
<h3>Horizontal scroll example</h3>
<p>With many columns, the table enables horizontal scroll so each column keeps a proper width</p>
<!-- No scroll limit - auto -->
<h4>Auto horizontal scroll (unlimited)</h4>
<bp-table
:data="list"
border
row-key="id"
style="width: 800px;"
>
<template #columns>
<bp-table-column title="ID" data-index="id" :width="80" />
<bp-table-column title="Name" data-index="name" :width="120" />
<bp-table-column title="Age" data-index="age" :width="80" />
<bp-table-column title="City" data-index="city" :width="120" />
<bp-table-column title="Job" data-index="job" :width="150" />
<bp-table-column title="Email" data-index="email" :width="200" />
<bp-table-column title="Phone" data-index="phone" :width="150" />
<bp-table-column title="Address" data-index="address" :width="250" />
<bp-table-column title="Company" data-index="company" :width="180" />
<bp-table-column title="Salary" data-index="salary" :width="120" />
</template>
</bp-table>
<!-- Explicit horizontal scroll width -->
<h4>Explicit horizontal scroll width (1200px)</h4>
<bp-table
:data="list"
border
row-key="id"
:scroll="{ x: 1200 }"
style="width: 600px;"
>
<template #columns>
<bp-table-column title="ID" data-index="id" :width="80" />
<bp-table-column title="Name" data-index="name" :width="120" />
<bp-table-column title="Age" data-index="age" :width="80" />
<bp-table-column title="City" data-index="city" :width="120" />
<bp-table-column title="Job" data-index="job" :width="150" />
<bp-table-column title="Email" data-index="email" :width="200" />
<bp-table-column title="Phone" data-index="phone" :width="150" />
<bp-table-column title="Address" data-index="address" :width="250" />
<bp-table-column title="Company" data-index="company" :width="180" />
<bp-table-column title="Salary" data-index="salary" :width="120" />
</template>
</bp-table>
<!-- Horizontal and vertical scroll -->
<h4>Horizontal + vertical scroll</h4>
<bp-table
:data="bigList"
border
row-key="id"
:scroll="{ x: 1000, y: 300 }"
style="width: 700px;"
>
<template #columns>
<bp-table-column title="ID" data-index="id" :width="80" />
<bp-table-column title="Name" data-index="name" :width="120" />
<bp-table-column title="Age" data-index="age" :width="80" />
<bp-table-column title="City" data-index="city" :width="120" />
<bp-table-column title="Job" data-index="job" :width="150" />
<bp-table-column title="Email" data-index="email" :width="200" />
<bp-table-column title="Phone" data-index="phone" :width="150" />
<bp-table-column title="Address" data-index="address" :width="250" />
</template>
</bp-table>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
const list = ref([
{
id: 1,
name: "Zhang San",
age: 28,
city: "Beijing",
job: "Frontend Engineer",
email: "zhangsan@example.com",
phone: "13800138001",
address: "1 Jianguomenwai Ave, Chaoyang, Beijing",
company: "Tech Co., Ltd.",
salary: "15000"
},
{
id: 2,
name: "Li Si",
age: 32,
city: "Shanghai",
job: "Backend Engineer",
email: "lisi@example.com",
phone: "13800138002",
address: "100 Century Avenue, Pudong, Shanghai",
company: "Internet Company",
salary: "18000"
},
{
id: 3,
name: "Wang Wu",
age: 26,
city: "Shenzhen",
job: "UI Designer",
email: "wangwu@example.com",
phone: "13800138003",
address: "South Science Park, Nanshan, Shenzhen",
company: "Design Studio",
salary: "12000"
},
{
id: 4,
name: "Zhao Liu",
age: 30,
city: "Guangzhou",
job: "Product Manager",
email: "zhaoliu@example.com",
phone: "13800138004",
address: "Zhujiang New Town, Tianhe, Guangzhou",
company: "Startup",
salary: "20000"
}
]);
// Extra rows for vertical scroll
const bigList = ref([
...list.value,
...Array.from({ length: 20 }, (_, i) => ({
id: i + 5,
name: `User ${i + 5}`,
age: 25 + (i % 10),
city: ["Beijing", "Shanghai", "Shenzhen", "Guangzhou", "Hangzhou"][i % 5],
job: ["Software Engineer", "Designer", "Product Manager", "QA Engineer", "Operations"][i % 5],
email: `user${i + 5}@example.com`,
phone: `1380013800${i + 5}`,
address: `Address ${i + 5}`,
company: `Company ${i + 5}`,
salary: `${10000 + i * 1000}`
}))
]);
</script>
<style scoped>
h3, h4 {
margin: 20px 0 10px 0;
color: #333;
}
p {
margin: 10px 0;
color: #666;
font-size: 14px;
}
.bp-table {
margin-bottom: 30px;
}
</style>Table Props
| v-model:selected-key | Selected key (radio) | StringNumber | - | - |
| v-model:selected-keys | Selected keys (checkbox) | Array | - | - |
| data | Data source | Array | [] | - |
| height | Fixed height | String | - | - |
| border | Whether bordered | Boolean | - | - |
| stripe | Whether striped | Boolean | - | - |
| row-key | Row key | String | id | - |
| loading | Whether loading | Boolean | - | - |
| spin-icon | Loading icon | NumberComponent | 1 | - |
| description | Loading description | String | - | - |
| empty-text | Empty data text | String | No data | - |
| row-selection | Row selection config | TableRowSelection | null | - |
| scroll | Scroll config | TableScroll | {} | - |
TableColumn Props
| title | Column title | String | - | - |
| data-index | Field name | String | - | - |
| width | Column width | NumberString | - | - |
| min-width | Min column width | NumberString | - | - |
| fixed | Fixed column | String | - | - |
| align | Alignment | String | left | - |
| ellipsis | Whether to ellipsis overflow | Boolean | - | - |
| tooltip | Whether to show tooltip | Boolean | - | - |
Table Events
| select-all | Triggered on select-all toggle | val: boolean | - |
| select | Triggered when selected rows change | vals: CheckboxValue[], rowKey: RadioValue, record: any | - |
| selection-change | Triggered when checkbox selection changes | vals: CheckboxValue[] | - |
Table Slots
| columns | Column definitions | - | - |
| empty | Empty-state content | - | - |
TableColumn Slots
| cell | Cell content | { record, rowIndex } | - |