vue-table-dynamic
Version:
A vue component of dynamic table
852 lines (729 loc) • 23.6 kB
Markdown
# vue-table-dynamic
简体中文 | [English](./README.md)
[vue-table-dynamic](https://github.com/TheoXiong/vue-table-dynamic) 是一个动态表格组件。面向运行时,实时响应源数据变化,动态更新表格内容与形态。具有丰富的特性,所有特性均可按需引入,满足多样化需求。
## 特性
- [多选](#多选)
- [搜索](#搜索)
- [排序](#排序)
- [筛选](#筛选)
- [分页](#分页)
- [编辑](#编辑])
- [边框](#边框)
- [条纹](#条纹)
- [高亮](#高亮)
- [配置列宽](#配置列宽)
- [配置表头](#配置表头)
- [固定表头](#固定表头)
- [固定列](#固定列)
- [作用域插槽](#作用域插槽)
## Demo
[https://theoxiong.github.io/vue-table-dynamic/](https://theoxiong.github.io/vue-table-dynamic/)

## 安装
```
$ npm install vue-table-dynamic --save
```
## 使用
### 引入模块
```
import VueTableDynamic from 'vue-table-dynamic'
```
### 注册
#### 全局注册
```
Vue.use(VueTableDynamic)
```
#### 组件内注册
```
<script>
export default {
components: { VueTableDynamic }
}
</script>
```
### 基础表格
基础表格用法

```
<template>
<div class="base-demo" style="width: 400px">
<vue-table-dynamic :params="params"></vue-table-dynamic>
</div>
</template>
<script>
import VueTableDynamic from 'vue-table-dynamic'
export default {
name: 'Demo',
data() {
return {
params: {
data: [
['Cell-1', 'Cell-2', 'Cell-3'],
['Cell-4', 'Cell-5', 'Cell-6'],
['Cell-7', 'Cell-8', 'Cell-9']
]
}
}
},
components: { VueTableDynamic }
}
</script>
```
### 边框
配置`border`属性,使用带边框表格

```
<template>
<div style="width: 600px">
<vue-table-dynamic :params="params" ref="table"></vue-table-dynamic>
</div>
</template>
<script>
import VueTableDynamic from 'vue-table-dynamic'
export default {
name: 'Demo',
data() {
return {
params: {
data: [
['Index', 'Data1', 'Data2', 'Data3'],
[1, 'b3ba90', '7c95f7', '9a3853'],
[2, 'ec0b78', 'ba045d', 'ecf03c'],
[3, '63788d', 'a8c325', 'aab418']
],
header: 'row',
border: true
}
}
},
components: { VueTableDynamic }
}
</script>
```
### 条纹
配置`stripe`属性,显示行条纹

```
<template>
<div style="width: 600px">
<vue-table-dynamic :params="params" ref="table"></vue-table-dynamic>
</div>
</template>
<script>
import VueTableDynamic from 'vue-table-dynamic'
export default {
name: 'Demo',
data() {
return {
params: {
data: [
['Index', 'Data1', 'Data2', 'Data3'],
[1, 'b3ba90', '7c95f7', '9a3853'],
[2, 'ec0b78', 'ba045d', 'ecf03c'],
[3, '63788d', 'a8c325', 'aab418'],
[4, 'hf7y8c', '4rghjk', 'cgnhik']
],
header: 'row',
border: true,
stripe: true
}
}
},
components: { VueTableDynamic }
}
</script>
```
### 高亮
配置`highlight`属性,指定行/列/单元高亮
- `highlight`类型为`{row?:Array<number>; column?:Array<number>; cell?:Array<[number,number]>;}`。如:`{row: [1], column: [1], cell: [[-1, -1]]}`,负数表示倒序索引
- `highlightedColor:`*`string`* 设置高亮背景色

```
<template>
<div style="width: 600px">
<vue-table-dynamic :params="params" ref="table"></vue-table-dynamic>
</div>
</template>
<script>
import VueTableDynamic from 'vue-table-dynamic'
export default {
name: 'Demo',
data() {
return {
params: {
data: [
['Index', 'Data1', 'Data2', 'Data3'],
[1, 'b3ba90', '7c95f7', '9a3853'],
[2, 'ec0b78', 'ba045d', 'ecf03c'],
[3, '63788d', 'a8c325', 'aab418'],
[4, 'hf7y8c', '4rghjk', 'cgnhik']
],
header: 'row',
border: true,
stripe: true,
highlight: { column: [-2] },
highlightedColor: 'rgb(243, 235, 200)'
}
}
},
components: { VueTableDynamic }
}
</script>
```
### 多选
配置`showCheck`属性,启用多选功能
- 通过`select`事件和`selection-change`事件,监听用户勾选操作
- 通过`getCheckedRowDatas`方法获取当前所有选中的行数据
- 通过`setAllRowChecked`方法将选中状态切换为全选或清空选择

```
<template>
<div style="width: 600px">
<vue-table-dynamic
:params="params"
@select="onSelect"
@selection-change="onSelectionChange"
ref="table"
>
</vue-table-dynamic>
</div>
</template>
<script>
import VueTableDynamic from 'vue-table-dynamic'
export default {
name: 'Demo',
data() {
return {
params: {
data: [
['Index', 'Data1', 'Data2', 'Data3'],
[1, 'b3ba90', '7c95f7', '9a3853'],
[2, 'ec0b78', 'ba045d', 'ecf03c'],
[3, '63788d', 'a8c325', 'aab418']
],
header: 'row',
showCheck: true
}
}
},
methods: {
onSelect (isChecked, index, data) {
console.log('onSelect: ', isChecked, index, data)
console.log('Checked Data:', this.$refs.table.getCheckedRowDatas(true))
},
onSelectionChange (checkedDatas, checkedIndexs, checkedNum) {
console.log('onSelectionChange: ', checkedDatas, checkedIndexs, checkedNum)
}
},
components: { VueTableDynamic }
}
</script>
```
### 搜索
配置`enableSearch`属性,启用全局搜索功能,仅显示匹配到搜索关键字的行
- 通过 `search:`*`function(value:string, included:array, excluded:array)`* 方法可以手动对行搜索过滤,适用于自定义搜索框(配置`enableSearch`为`false`)

```
<template>
<div style="width: 600px">
<vue-table-dynamic
:params="params"
ref="table"
>
</vue-table-dynamic>
</div>
</template>
<script>
import VueTableDynamic from 'vue-table-dynamic'
export default {
name: 'Demo',
data() {
return {
params: {
data: [
['Index', 'Data1', 'Data2', 'Data3'],
[1, 'b3ba90', '7c95f7', '9a3853'],
[2, 'ec0b78', 'ba045d', 'ecf03c'],
[3, '63788d', 'a8c325', 'aab418']
],
header: 'row',
enableSearch: true
}
}
},
methods: {
},
components: { VueTableDynamic }
}
</script>
```
### 排序
配置`sort`属性,启用排序功能,基于列数据对行进行排序
- `sort`类型为`Array<number>`,数组成员为启用排序的列索引。如:`sort: [0, 1]`,基于第0列和第1列排序

```
<template>
<div style="width: 600px">
<vue-table-dynamic
:params="params"
ref="table"
>
</vue-table-dynamic>
</div>
</template>
<script>
import VueTableDynamic from 'vue-table-dynamic'
export default {
name: 'Demo',
data() {
return {
params: {
data: [
['Index', 'Data1', 'Data2', 'Data3'],
[1, 'b3ba90', '7c95f7', '9a3853'],
[2, 'ec0b78', 'ba045d', 'ecf03c'],
[3, '63788d', 'a8c325', 'aab418']
],
header: 'row',
sort: [0, 1]
}
}
},
methods: {
},
components: { VueTableDynamic }
}
</script>
```
### 筛选
通过`filter`配置具有筛选功能的列以及筛选条件
- `filter`类型为`Array<{column:number; content:Array<{text:string; value:string|number;}>; method:function;}>`。 如:`[{column: 0, content: [{text: '> 2', value: 2}], method: (value, cell) => { return cell.data > value }}]`
- `filter[].column` 列索引
- `filter[].content`筛选项
- `filter[].method` 筛选的方法,如果是多选的筛选项,对每一条数据会执行多次,任意一次返回 true 就会显示。

```
<template>
<div style="width: 600px">
<vue-table-dynamic
:params="params"
ref="table"
>
</vue-table-dynamic>
</div>
</template>
<script>
import VueTableDynamic from 'vue-table-dynamic'
export default {
name: 'Demo',
data() {
return {
params: {
data: [
['Index', 'Data1', 'Data2', 'Time'],
[1, 'b3ba90', '9a3853', '2019-01-01 10:10'],
[2, 'ec0b78', 'ecf03c', '2019-02-02 11:11'],
[3, '7c95f7', 'fdf451', '2019-02-02 12:12'],
[4, 'ba045d', '34fdgh', '2019-02-02 13:13'],
[5, 'a8c325', '4678de', '2019-03-03 14:14']
],
header: 'row',
filter: [{
column: 0,
content: [{text: '> 2', value: 2}, {text: '> 4', value: 4}],
method: (value, tableCell) => { return tableCell.data > value }
}, {
column: 3,
content: [{text: '2019-01-01', value: '2019-01-01'}, {text: '2019-02-02', value: '2019-02-02'}],
method: (value, tableCell) => { return String(tableCell.data).toLocaleLowerCase().includes(String(value).toLocaleLowerCase()) }
}],
}
}
},
methods: {
},
components: { VueTableDynamic }
}
</script>
```
### 分页
配置`pagination`属性,启用分页功能,支持配置每页显示条数和条数可选项
- `pagination:boolean`为`true`时启用分页功能
- `pageSize?:number` 每页显示行数,默认为`10`
- `pageSizes?:Array<number>` 每页行数可选项,默认为`[10, 20, 50, 100]`

```
<template>
<div style="width: 600px">
<vue-table-dynamic
:params="params"
ref="table"
>
</vue-table-dynamic>
</div>
</template>
<script>
import VueTableDynamic from 'vue-table-dynamic'
const random = () => {
return parseInt(Date.now() + Math.random() * 10000000).toString(16).slice(-6)
}
export default {
name: 'Demo',
data() {
return {
params: {
data: [
['Index', `Data1`, `Data2`, `Data3`]
],
header: 'row',
border: true,
stripe: true,
pagination: true,
pageSize: 5,
pageSizes: [5, 10, 20, 50]
}
}
},
mounted () {
for (let i = 0; i < 100; i++) {
this.params.data.push([i+1, `${random()}`, `${random()}`, `${random()}`])
}
},
components: { VueTableDynamic }
}
</script>
```
### 编辑
配置`edit`属性,启用编辑功能,支持配置某行/某列/某个表格单元可编辑
- `edit`类型为`{row?:Array<number>; column?:Array<number>; cell?:Array<[number,number]>;}`。如:`{row: [1], column: [1], cell: [[-1, -1]]}`,负数表示倒序索引
- 配置为`{row: 'all'}`时,所有单元均可编辑
- 通过`cell-change`事件,监听编辑操作
- 编辑会改变当前数据,不会改变传入的源数据
- 通过`getData`方法,可获取编辑后的最新数据
- 如果配置了 `header: 'row'`,则第一行表头不可编辑
- 如果源数据为`number`类型, 则仅在输入数字时有效

```
<template>
<div style="width: 600px">
<vue-table-dynamic
:params="params"
@cell-change="onCellChange"
ref="table"
>
</vue-table-dynamic>
</div>
</template>
<script>
import VueTableDynamic from 'vue-table-dynamic'
export default {
name: 'Demo',
data() {
return {
params: {
data: [
['Index', 'Data1', 'Data2', 'Data3'],
[1, 'b3ba90', '7c95f7', '9a3853'],
[2, 'ec0b78', 'ba045d', 'ecf03c'],
[3, '63788d', 'a8c325', 'aab418']
],
header: 'row',
edit: {
row: [1],
column: [1],
cell: [[-1, -1]]
}
}
}
},
methods: {
onCellChange (rowIndex, columnIndex, data) {
console.log('onCellChange: ', rowIndex, columnIndex, data)
console.log('table data: ', this.$refs.table.getData())
}
},
components: { VueTableDynamic }
}
</script>
```
### 配置列宽
通过`columnWidth`属性配置表格列宽度
- `columnWidth`类型为`Array<{column:number; width:number|string;}>`。如:`[{column: 0, width: 60}, {column: 3, width: '15%'}]`
- `columnWidth[].column` 列索引
- `columnWidth[].width` 列宽度,支持像素值(number)和百分比(string)

```
<template>
<div style="width: 600px">
<vue-table-dynamic :params="params" ref="table"></vue-table-dynamic>
</div>
</template>
<script>
import VueTableDynamic from 'vue-table-dynamic'
export default {
name: 'Demo',
data() {
return {
params: {
data: [
['Index', 'Data1', 'Data2', 'Data3'],
[1, 'b3ba90', '7c95f7', '9a3853'],
[2, 'ec0b78', 'ba045d', 'ecf03c'],
[3, '63788d', 'a8c325', 'aab418']
],
header: 'row',
border: true,
columnWidth: [{column: 0, width: 60}, {column: 3, width: '15%'}],
}
}
},
components: { VueTableDynamic }
}
</script>
```
### 配置表头
通过`header`属性配置表头
- `header: row` 首行为表头
- `header: column` 首列为表头
- `header: ''` 无表头

```
<template>
<div style="width: 600px">
<vue-table-dynamic :params="params" ref="table"></vue-table-dynamic>
</div>
</template>
<script>
import VueTableDynamic from 'vue-table-dynamic'
export default {
name: 'Demo',
data() {
return {
params: {
data: [
['Index', 'Data1', 'Data2', 'Data3'],
[1, 'b3ba90', '7c95f7', '9a3853'],
[2, 'ec0b78', 'ba045d', 'ecf03c'],
[3, '63788d', 'a8c325', 'aab418']
],
header: 'column',
border: true,
columnWidth: [{column: 0, width: 60}]
}
}
},
components: { VueTableDynamic }
}
</script>
```
### 固定表头
通过`height`配置表格高度即可固定表头。当表格超出配置高度,垂直滚动时首行表头会固定不动
- `height: number` 表格可视高度
- 当`header`不为`row`时,首行被视为普通表格行,会跟随滚动

```
<template>
<div style="width: 600px">
<vue-table-dynamic
:params="params"
ref="table"
>
</vue-table-dynamic>
</div>
</template>
<script>
import VueTableDynamic from 'vue-table-dynamic'
const random = () => {
return parseInt(Date.now() + Math.random() * 10000000).toString(16).slice(-6)
}
export default {
name: 'Demo',
data() {
return {
params: {
data: [
['Index', `Data1`, `Data2`, `Data3`]
],
header: 'row',
border: true,
stripe: true,
height: 180
}
}
},
mounted () {
for (let i = 0; i < 12; i++) {
this.params.data.push([i+1, `${random()}`, `${random()}`, `${random()}`])
}
},
components: { VueTableDynamic }
}
</script>
```
### 固定列
通过`fixed`配置需要固定的列。当表格内容宽度超出容器宽度时,出现水平滚动条。水平滚动时,固定的列不会移动
- `fixed: number` 需要固定的列。
- 索引小于等于`fixed`的列都会配置为固定。如`fixed`为1时,第0列和第1列被配置为固定
- 对于配置为固定的列,需要通过`columnWidth`指定列的宽度(像素值)
- 多选框不在固定列索引范围内。即:有多选框时,第0列为内容列,多选框始终在第0列前面
- 如果需要将中间某列内容固定,可以将params.data中该列数据调整到第0列

```
<template>
<div style="width: 600px">
<vue-table-dynamic :params="params" ref="table"></vue-table-dynamic>
</div>
</template>
<script>
import VueTableDynamic from 'vue-table-dynamic'
const random = () => {
return parseInt(Date.now() + Math.random() * 10000000).toString(16).slice(-6)
}
export default {
name: 'Demo',
data() {
return {
params: {
data: [
['Index', `Data1`, `Data2`, `Data3`]
],
header: 'row',
border: true,
stripe: true,
columnWidth: [{column: 0, width: 100}, {column: 2, width: 400}],
fixed: 0
}
}
},
mounted () {
for (let i = 0; i < 5; i++) {
this.params.data.push([i+1, `${random()}`, `${random()}`, `${random()}`])
}
},
components: { VueTableDynamic }
}
</script>
```
### 固定表头和列
通过`height`固定表头, 通过`fixed`配置需要固定的列

```
<template>
<div style="width: 600px">
<vue-table-dynamic :params="params" ref="table"></vue-table-dynamic>
</div>
</template>
<script>
import VueTableDynamic from 'vue-table-dynamic'
const random = () => {
return parseInt(Date.now() + Math.random() * 10000000).toString(16).slice(-6)
}
export default {
name: 'Demo',
data() {
return {
params: {
data: [
['Index', `Data1`, `Data2`, `Data3`]
],
header: 'row',
border: true,
stripe: true,
columnWidth: [{column: 0, width: 100}, {column: 2, width: 400}],
height: 180,
fixed: 0
}
}
},
mounted () {
for (let i = 0; i < 10; i++) {
this.params.data.push([i+1, `${random()}`, `${random()}`, `${random()}`])
}
},
components: { VueTableDynamic }
}
</script>
```
### 作用域插槽
通过作用域插槽,可自定义cell内容
具名插槽的名称为 `column-n`, n为列索引
```
<template>
<div class="base-demo" style="width: 400px">
<vue-table-dynamic :params="params">
<template v-slot:column-1="{ props }">
<span>Slot::{{props.cellData}}--{{props.row}}--{{props.column}}</span>
</template>
</vue-table-dynamic>
</div>
</template>
<script>
import VueTableDynamic from 'vue-table-dynamic'
export default {
name: 'Demo',
data() {
return {
params: {
data: [
['Cell-1', 'Cell-2', 'Cell-3'],
['Cell-4', 'Cell-5', 'Cell-6'],
['Cell-7', 'Cell-8', 'Cell-9']
]
}
}
},
components: { VueTableDynamic }
}
</script>
```
## API
### 属性
- 传入到组件的`props`只有`params`对象,下表的属性均为`params`对象的一级属性
- `data`为必需属性,其他均为可选项
| 属性名 | 说明 | 类型 | 可选值 | 默认值 |
| ----| --------- | ------- | ------------- | --------- |
| `data` | 表格源数据 | `Array<[number, ..., number]>` | - | `[]` |
| `header` | 表头配置 | `string` | `row`: 首行表头; `column`: 首列表头; 其他: 无 | 无表头 |
| `border` | 是否带边框 | `boolean` | `true`/`false` | `false` |
| `stripe` | 是否带条纹 | `boolean` | `true`/`false` | `false` |
| `highlight` | 高亮的行/列/表单元。值为负数时,表示倒序索引 | {row?:Array<>; column?:Array<>; cell?:Array<>;} | - | `{}` |
| `highlightedColor` | 高亮的颜色 | `string` | - | `#EBEBEF` |
| `wordWrap` | 表格单元文本的word-wrap样式 | `string` | `normal/break-word` | `normal` |
| `whiteSpace` | 表格单元文本的white-space样式 | `string` | `nowrap/normal/pre/pre-wrap/pre-line` | `nowrap` |
| `textOverflow` | 表格单元文本的text-overflow样式 | `string` | `clip/ellipsis` | `clip` |
| `showCheck` | 显示多选框。仅当`header`为`row`时,第一行第一列为全选框,否则第一列均为当前行的勾选框 | `boolean` | `true`/`false` | `false` |
| `enableSearch` | 使用全局搜索功能 | `boolean` | `true`/`false` | `false` |
| `minWidth` | 表最小宽度 | `number` | - | `100` |
| `maxWidth` | 表最大宽度 | `number` | - | `10000` |
| `height` | 表可视高度。通过配置表格高度,(当`header`为`row`时)可固定表头。当表格超出配置高度,垂直滚动时首行表头会固定不动 | `number` | - | - |
| `fixed` | 固定列,需要与columnWidth配合 | `number` | `>= 0` | |
| `headerHeight` | 表头高度 | `number` | `>= 24` | `30` |
| `rowHeight` | 行高 | `number` | `>= 24` | `30` |
| `columnWidth` | 指定某一列或某几列的宽度,剩余列宽度均分。`width`值可为绝对值或相对百分比 | Array<{column: number; width: number/string;}> | - | - |
| `sort` | 指定可排序的列 | `Array<number>` | - | - |
| `filter` | 指定可筛选的列。`column`为列索引; `content`为筛选项; `method` 为筛选的方法,同时选中多个筛选项时任意一次返回true就会显示 | Array<{column, content, method}> | - | - |
| `edit` | 可编辑的 行、列、表单元。负数表示倒序(如`-1`为最后`1`行、列)配置`row`为` 'all'`时,所有行可编辑。编辑会改变当前数据,不会改变传入的源数据| {row?: Array<>; column?: Array<>; cell?: Array<>;} | - | - |
| `pagination` | 使用分页 | `boolean` | `true`/`false` | `false` |
| `pageSize` | 每页行数 | `number` | - | `10` |
| `pageSizes` | 每页行数的可选项 | `Array<number>` | - | |
| `showTotal` | 显示分页总数 | `boolean` | `true`/`false` | `false` |
| `scrollbar` | 滚动条的显示时机 | `string` | `show/hover/hidden` | `show` |
### 方法
| 方法名 | 说明 | 参数 | 返回 |
| ------- | -------- | --------- | ---------- |
| `getData` | 获取表格数据。当使用编辑功能时,可使用此方法获取编辑后的最新数据 | 无 | `Array<[number, ..., number]>` |
| `getCheckedRowDatas` | 使用多选功能时,获取选中行的数据 | `includeWhenHeaderInfirstRow: boolean` 当首行为表头时,是否包含表头行,默认`false` | `Array<[number, ..., number]>` |
| `getRowData` | 根据行索引获取指定行的数据 | `rowIndex: number` 行索引;`isCurrent: boolean`索引是否为排序后的索引,默认false,即原始索引 | `Array<number>` |
| `search` | 手动对行搜索过滤,适用于自定义搜索框(配置`enableSearch`为`false`) | `searchValue: string`搜索的关键字; `included:array` 在指定的列里进行匹配; `excluded:array` 不在指定的列里匹配, 优先级高于`included` | 无 |
| `clearSearch` | 取消搜索过滤,显示所有行 | 无 | 无 |
| `toPage` | (分页时)跳转到目标页 | `tagetPage:number` 目标页索引 | - |
### 事件
| 事件名 | 说明 | 回调参数 |
| ------------- | ------------------------ | -----------------------------------------------------------|
| `select` | 行的选中/取消选中 | `checked: boolean`; ` index: number`; `data: Array<string\number>` |
| `select-all` | 全选/取消全选 | `isCheckedAll: boolean` |
| `row-click` | 点击行 | ` index: number`; ` data: Array<string\number>` |
| `cell-click` | 点击表格单元 | `rowIndex: number`; `columnIndex: number`; ` data: string\number` |
| `cell-contextmenu` | 右键表格单元 | `rowIndex: number`; `columnIndex: number`; ` data: string\number` |
| `cell-change` | 表格单元数据(编辑)改变 | `rowIndex: number`; `columnIndex: number`; ` data: string\number` |
| `sort-change` | 排序 | `index: number`; `value: string` |