Table 表格
如果项目中使用的是 1.x 版本的基础组件(@alifd/next),请在左侧导航顶部切换组件版本。
安装方法
- 在命令行中执行以下命令
npm install @icedesign/base@latest -S
Guide
Table负责将数据呈现为高度可定制和具备可访问性的HTML表格,其核心功能为将结构化的数据使用表格的方式展现,然后可以使用各种参数来向表格中加入一些特性,比如排序,过滤,滚动,锁列等。
基本使用
基本的Table包含行和列,使用Table.Column来定义列的信息,使用传入的dataSource属性数据来创建行。
下面的代码将会创建一行两列的数据表。
const dataSource = [{id: 1, time: '2016'}];
ReactDOM.render(<Table dataSource={dataSource}>
<Table.Column title="Id" dataIndex="id"/>
<Table.Column title="Time" dataIndex="time"/>
</Table>, mountNode)
列配置
Table.Column提供了非常多的配置属性用于自定义列,最常见的就是使用cell
自定义单元格的渲染逻辑. 其他的配置选项可以参考下面的Table.Column的API
下面的代码会让cell根据值渲染不同的视图
const dataSource = [{id: 1, time: '2016'}];
const renderTime = value => {
if (value == '2016') {
return '今年';
}
return value;
}
ReactDOM.render(<Table dataSource={dataSource}>
<Table.Column title="Id" dataIndex="id"/>
<Table.Column title="Time" dataIndex="time" cell={renderTime}/>
</Table>, mountNode)
多表头
使用Table.ColumnGroup包裹Table.Column来创建有多个表头的表格
const dataSource = [{id: 1, time: '2016'}];
ReactDOM.render(<Table dataSource={dataSource}>
<Table.ColumnGroup>
<Table.Column title="Id" dataIndex="id"/>
<Table.Column title="Time" dataIndex="time"/>
</Table.ColumnGroup>
<Table.ColumnGroup>
<Table.Column title="Id" dataIndex="id"/>
</Table.ColumnGroup>
</Table>, mountNode)
已知问题
GroupList不支持在Hover状态和选中状态下显示背景色
无法完全支持在锁列的情况下合并单元格
无法支持在锁列的区域和非锁列的区域内合并单元格
性能问题
由于React的机制问题,在做与Table无关的更新的时候,可能会导致diff计算花费大量的时间,
在你确认只有props和state才能影响Table渲染的情况下,可以设置optimization
为true
来开启, 原理就是通过
shouldComponentUpdate
的生命周期来对比props和state的变更,开启了该选项后可能导致下面的副作用。
class App extends React.Component{
state = {
extra: 'abc'
}
cellRender = (value) => {
return value + this.state.extra;
}
render(){
return <Table dataSource={[{id: 1}]}>
<Table.Column cell={this.cellRender} dataIndex="id"/>
</Table>
}
componentDidMount(){
setTimeout(() => {
this.setState({
extra: 'bcd'
})
},1000)
}
}
上面的代码在componentDidMount
之后的setState
虽然更新了extra
, 但是并不会触发Table的重新渲染。
解决方式如下:
- 将cellRender访问的state通过props的方式传入。
class App extends React.Component{
state = {
extra: 'abc'
}
cellRender = (value, index, record, context) => {
return value + context.props.extra;
}
render(){
return <Table dataSource={[{id: 1}]} extra={this.state.extra}>
<Table.Column cell={this.cellRender} dataIndex="id"/>
</Table>
}
componentDidMount(){
setTimeout(() => {
this.setState({
extra: 'bcd'
})
},1000)
}
}
- 通过设置
optimization
为false
来关闭Table的shouldComponentUpdate
配置。
class App extends React.Component{
state = {
extra: 'abc'
}
cellRender = (value, index, record, context) => {
return value + this.state.extra;
}
render(){
return <Table dataSource={[{id: 1}]} optimization={false}>
<Table.Column cell={this.cellRender} dataIndex="id"/>
</Table>
}
componentDidMount(){
setTimeout(() => {
this.setState({
extra: 'bcd'
})
},1000)
}
}
API
表格
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
prefix | 样式类名的品牌前缀 | String | 'next-' |
className | 自定义类名 | String | - |
style | 自定义内联样式 | Object | - |
dataSource | 表格展示的数据源 | Array | [] |
rowSelection | 是否启用选择模式属性:getProps: {Function} Function(record)=>Object 获取selection的默认属性onChange: {Function} Function(selectedRowKeys:Array, records:Array) 选择改变的时候触发的事件,注意: 其中records只会包含当前dataSource的数据,很可能会小于selectedRowKeys的长度。onSelect: {Function} Function(selected:Boolean, record:Object, records:Array) 用户手动选择/取消选择某行的回调onSelectAll: {Function} Function(selected:Boolean, records:Array) 用户手动选择/取消选择所有行的回调selectedRowKeys: {Array} 设置了此属性,将rowSelection变为受控状态,接收值为该行数据的primaryKey的值mode: {String} 选择selection的模式, 可选值为single , multiple ,默认为multiple | Object | null |
onRowClick | 点击表格每一行触发的事件签名:Function(record: Object, index: Number, e: Event) => void参数:record: {Object} 该行所对应的数据index: {Number} 该行所对应的序列e: {Event} DOM事件对象 | Function | () => {} |
onRowMouseEnter | 悬浮在表格每一行的时候触发的事件签名:Function(record: Object, index: Number, e: Event) => void参数:record: {Object} 该行所对应的数据index: {Number} 该行所对应的序列e: {Event} DOM事件对象 | Function | () => {} |
onRowMouseLeave | 离开表格每一行的时候触发的事件签名:Function(record: Object, index: Number, e: Event) => void参数:record: {Object} 该行所对应的数据index: {Number} 该行所对应的序列e: {Event} DOM事件对象 | Function | () => {} |
onSort | 点击列排序触发的事件签名:Function(dataIndex: String, order: String) => void参数:dataIndex: {String} 指定的排序的字段order: {String} 排序对应的顺序, 有desc 和asc 两种 | Function | () => {} |
onFilter | 点击过滤确认按钮触发的事件签名:Function(filterParams: Object) => void参数:filterParams: {Object} 过滤的字段信息 | Function | () => {} |
getRowClassName | 设置每一行的样式名称签名:Function(record: Object, index: Number) => String参数:record: {Object} 该行所对应的数据index: {Number} 该行所对应的序列返回值:{String} 需要设置的样式名称 | Function | () => {} |
getRowProps | 设置每一行的属性,如果返回值和其他针对行操作的属性冲突则无效。签名:Function(record: Object, index: Number) => Object参数:record: {Object} 该行所对应的数据index: {Number} 该行所对应的序列返回值:{Object} 需要设置的行属性 | Function | () => {} |
getCellProps | 设置单元格的属性,通过该属性可以进行合并单元格签名:Function(rowIndex: Number, colIndex: Number, record: Object) => Object参数:rowIndex: {Number} 该列所对应的序列colIndex: {Number} 该行所对应的序列record: {Object} 该行对应的记录返回值:{Object} 返回td元素的所支持的属性对象 | Function | () => {} |
fixedHeader | 表头是否固定,该属性配合maxBodyHeight使用,当内容区域的高度超过maxBodyHeight的时候,在内容区域会出现滚动条 | Boolean | false |
maxBodyHeight | 最大内容区域的高度,在fixedHeader 为true 的时候,超过这个高度会出现滚动条 | Number | 200 |
hasBorder | 表格是否具有边框 | Boolean | true |
hasHeader | 表格是否具有头部 | Boolean | true |
isZebra | 表格是否是斑马线 | Boolean | false |
isLoading | 表格是否在加载中 | Boolean | false |
primaryKey | dataSource当中数据的主键,如果给定的数据源中的属性不包含该主键,会造成选择状态全部选中 | String | 'id' |
filterParams | 当前过滤的的keys,使用此属性可以控制表格的头部的过滤选项中哪个菜单被选中,格式为 {dataIndex: {selectedKeys:[]}}示例:假设要控制dataIndex为id的列的过滤菜单中key为one的菜单项选中<Table filterParams={{id: {selectedKeys: ['one']}}}/> | Object | - |
sort | 当前排序的字段,使用此属性可以控制表格的字段的排序,格式为{dataIndex: 'asc'} | Object | - |
expandedRowRender | 额外渲染行的渲染函数签名:Function(record: Object, index: Number) => Element参数:record: {Object} 该行所对应的数据index: {Number} 该行所对应的序列返回值:{Element} null | Function | - |
expandedRowIndent | 额外渲染行的缩进 | Array | 1, 0 |
expandedRowKeys | 默认情况下展开的额外渲染行, 传入此属性为受控状态 | Array | - |
hasExpandedRowCtrl | 是否显示点击展开额外渲染行的+号按钮 | Boolean | true |
getExpandedColProps | 设置额外渲染行的属性签名:Function() => void | Function | () => {} |
onExpandedChange | 在额外渲染行展开或者收齐的时候触发的事件签名:Function(expandedRowKeys: Array, currentRowKey: String, expanded: Boolean, currentRecord: Object) => void参数:expandedRowKeys: {Array} 展开的渲染行的keycurrentRowKey: {String} 当前点击的渲染行的keyexpanded: {Boolean} 当前点击是展开还是收起currentRecord: {Object} 当前点击额外渲染行的记录 | Function | () => {} |
onExpandedRowClick | 点击额外渲染行触发的事件签名:Function(record: Object, index: Number, e: Event) => void参数:record: {Object} 该行所对应的数据index: {Number} 该行所对应的序列e: {Event} DOM事件对象 | Function | () => {} |
indentSize | 在tree模式下的缩进尺寸, 仅在isTree为true时候有效 | Number | 12 |
openRowKeys | 默认情况下展开的树形表格,传入了此属性代表tree的展开为受控操作 | Array | - |
onRowOpen | 点击tree展开或者关闭的时候触发的事件签名:Function(openRowKeys: Array, currentRowKey: String, opened: Boolean, currentRecord: Object) => void参数:openRowKeys: {Array} tree模式下展开的keycurrentRowKey: {String} 当前点击行的keyopened: {Boolean} 当前点击是展开还是收起currentRecord: {Object} 当前点击行的记录 | Function | () => {} |
isTree | 开启Table的tree模式, 接收的数据格式中包含children则渲染成tree table | Boolean | false |
optimization | 是否开启性能优化,开启了性能优化后,会自动加入shouldComponentUpdate | Boolean | false |
locale | 自定义国际化文案对象属性:empty: {String} 没有数据时的提示文案ok: {String} 过滤器中确认按钮文案reset: {String} 过滤器中重置按钮文案 | Object | - |
language | 自定义国际化语言可选值:'en-us', 'zh-cn', 'zh-tw' | Enum | - |
Table.ColumnGroup
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
title | 表头显示的内容 | ReactElement/ReactNode/Function | 'column-group' |
Table.Column
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
dataIndex | 指定列对应的字段,支持a.b 形式的快速取值 | String | - |
cell | 行渲染的逻辑Function(value, index, record) => Element | ReactElement/ReactNode/Function | (value) => value |
title | 表头显示的内容 | ReactElement/ReactNode/Function | 'column' |
sortable | 是否支持排序 | Boolean | - |
width | 在锁列的情况下需要配置的宽度 | ReactNode | - |
align | 单元格的对齐方式可选值:'left', 'center', 'right' | Enum | - |
filters | 生成标题过滤的菜单, 格式为[{label:'xxx', value:'xxx'}] | Array<Object> | - |
filterMode | 过滤的模式是单选还是多选可选值:'single', 'multiple' | Enum | 'multiple' |
lock | 是否支持锁列,可选值为left ,right , true | Boolean/String | - |
Table.GroupHeader
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
cell | 行渲染的逻辑 | ReactElement/ReactNode/Function | () => '' |
hasSelection | 是否在GroupHeader上面渲染selection | Boolean | false |
代码示例
简单的表格渲染
查看源码在线预览
import { Table } from "@icedesign/base";
const onRowClick = function(record, index, e) {
console.log(record, index, e);
},
getData = () => {
let result = [];
for (let i = 0; i < 5; i++) {
result.push({
title: {
name: `Quotation for 1PCS Nano ${3 + i}.0 controller compatible`
},
id: 100306660940 + i,
time: 2000 + i
});
}
return result;
},
render = (value, index, record) => {
return <a>Remove({record.id})</a>;
};
ReactDOM.render(
<Table dataSource={getData()} onRowClick={onRowClick}>
<Table.Column title="Id" dataIndex="id" />
<Table.Column title="Title" dataIndex="title.name" />
<Table.Column title="Time" dataIndex="time" />
<Table.Column cell={render} width="40%" />
</Table>,
mountNode
);
演示全选和单选受控的功能
查看源码在线预览
import { Table, Button } from "@icedesign/base";
const getData = () => {
let result = [];
for (let i = 0; i < 5; i++) {
result.push({
title: {
name: `Quotation for 1PCS Nano ${3 + i}.0 controller compatible`
},
id: 100306660940 + i,
time: 2000 + i
});
}
return result;
},
render = (value, index, record) => {
return <a>Remove({record.id})</a>;
};
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
rowSelection: {
onChange: this.onChange.bind(this),
onSelect: function(selected, record, records) {
console.log("onSelect", selected, record, records);
},
onSelectAll: function(selected, records) {
console.log("onSelectAll", selected, records);
},
selectedRowKeys: [],
getProps: record => {
return {
disabled: record.id === 100306660941
};
}
},
dataSource: getData(0, 5)
};
}
render() {
return (
<div>
<p>
<Button onClick={this.clear.bind(this)}>Clear Selection</Button>
<Button onClick={this.changeMode.bind(this)}>
Switch single mode
</Button>
<Button onClick={this.toggleLoading.bind(this)}>
Toggle loading
</Button>
<Button onClick={this.modifyDataSource.bind(this)}>
Modify dataSource
</Button>
</p>
<Table
dataSource={this.state.dataSource}
isLoading={this.state.isLoading}
rowSelection={this.state.rowSelection}
>
<Table.Column title="Id" dataIndex="id" />
<Table.Column title="Title" dataIndex="title.name" />
<Table.Column title="Time" dataIndex="time" />
<Table.Column cell={render} width={200} />
</Table>
</div>
);
}
onChange(ids, records) {
let { rowSelection } = this.state;
rowSelection.selectedRowKeys = ids;
console.log("onChange", ids, records);
this.setState({ rowSelection });
}
clear() {
let { rowSelection } = this.state;
rowSelection.selectedRowKeys = [];
this.setState({ rowSelection });
}
toggleLoading() {
this.setState({ isLoading: !this.state.isLoading });
}
changeMode() {
let { rowSelection } = this.state;
rowSelection.mode = "single";
this.setState({ rowSelection });
}
modifyDataSource() {
this.setState({
dataSource: getData(9, 14)
});
}
}
ReactDOM.render(<App />, mountNode);
通过getCellProps进行列合并。
查看源码在线预览
import { Table } from "@icedesign/base";
const onRowClick = function(record, index, e) {
console.log(record, index, e);
},
getData = () => {
let result = [];
for (let i = 0; i < 5; i++) {
result.push({
title: {
name: `Quotation for 1PCS Nano ${3 + i}.0 controller compatible`
},
id: 100306660940 + i,
time: 2000 + i
});
}
return result;
},
render = (value, index, record) => {
return <a>Remove({record.id})</a>;
},
getCellProps = (rowIndex, colIndex) => {
if (rowIndex === 2 && colIndex === 1) {
return {
colSpan: 2,
rowSpan: 3
};
}
if (rowIndex === 1 && colIndex === 2) {
return {
colSpan: 2,
rowSpan: 1
};
}
};
ReactDOM.render(
<Table
dataSource={getData()}
onRowClick={onRowClick}
getCellProps={getCellProps}
>
<Table.Column title="Id" dataIndex="id" />
<Table.Column title="Title" dataIndex="title.name" />
<Table.Column title="Time" dataIndex="time" />
<Table.Column cell={render} width={200} />
</Table>,
mountNode
);
定制显示的表格列数
查看源码在线预览
import { Table, Button, Dialog, Checkbox } from "@icedesign/base";
const { Group } = Checkbox;
const getData = () => {
let result = [];
for (let i = 0; i < 5; i++) {
result.push({
title: `Quotation for 1PCS Nano ${3 + i}.0 controller compatible`,
id: 100306660940 + i,
time: 2000 + i
});
}
return result;
},
cols = [
{
title: "id",
dataIndex: "id"
},
{
title: "Title",
dataIndex: "title"
},
{
title: "Time",
dataIndex: "time"
}
];
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
dataSource: getData(),
cols: cols
};
}
openDialog = () => {
Dialog.alert({
needWrapper: false,
content: this.renderControlContent(),
title: "选择需要显示的列",
onOk: () => {
this.setState({
cols: this.changedCols
});
}
});
};
renderControlContent() {
const groupSource = cols.map(col => {
return {
label: col.title,
value: col.dataIndex
};
}),
defaultValue = this.state.cols.map(col => col.dataIndex);
return (
<Group
dataSource={groupSource}
onChange={this.onChange}
defaultValue={defaultValue}
/>
);
}
onChange = value => {
this.changedCols = cols.filter(col => value.indexOf(col.dataIndex) > -1);
};
render() {
return (
<div>
<p>
<Button onClick={this.openDialog}> 选择显示的列数 </Button>
</p>
<Table dataSource={this.state.dataSource}>{this.renderCols()}</Table>
</div>
);
}
renderCols() {
const { cols } = this.state;
return cols.map(col => {
return (
<Table.Column
title={col.title}
dataIndex={col.dataIndex}
key={col.dataIndex}
/>
);
});
}
}
ReactDOM.render(<App />, mountNode);
演示对表格的增删改查
查看源码在线预览
import { Table, Button } from "@icedesign/base";
const onRowClick = function(record, index, e) {
console.log(record, index, e);
},
getData = () => {
let result = [];
for (let i = 0; i < 5; i++) {
result.push({
title: {
name: `Quotation for 1PCS Nano ${3 + i}.0 controller compatible`
},
id: 100306660940 + i,
time: 2000 + i
});
}
return result;
};
class App extends React.Component {
state = {
dataSource: getData()
};
render() {
const renderOper = (value, index, record) => {
return (
<a onClick={this.onRemove.bind(this, record.id)}>Remove({record.id})</a>
);
};
return (
<div>
<p>
<Button onClick={this.onAdd}>Add Item</Button>
</p>
<Table dataSource={this.state.dataSource} onRowClick={onRowClick}>
<Table.Column title="Id" dataIndex="id" />
<Table.Column title="Title" dataIndex="title.name" />
<Table.Column title="Time" dataIndex="time" />
<Table.Column cell={renderOper} width="20%" />
</Table>
</div>
);
}
onAdd = () => {
// 注意在没有通过shouldComponentUpdate判断的时候可以使用此写法
// 否则注意数组和对象的引用关系
const { dataSource } = this.state;
dataSource.push({
title: {
name: "Quotation for 1PCS Nano controller compatible"
},
id: Date.now(),
time: 2000
});
this.setState({
dataSource
});
};
onRemove = id => {
const { dataSource } = this.state;
let index = -1;
dataSource.forEach((item, i) => {
if (item.id === id) {
index = i;
}
});
if (index !== -1) {
dataSource.splice(index, 1);
this.setState({
dataSource
});
}
};
}
ReactDOM.render(<App />, mountNode);
可以通过 expandedRowRender
额外渲染行,但是会包含复杂的组件
查看源码在线预览
import { Table, Button } from "@icedesign/base";
/*eslint-disable react/prop-types, react/no-multi-comp*/
class ExpandedApp extends React.Component {
constructor(props) {
super(props);
this.state = {
dataSource: this.props.dataSource
};
}
render() {
const style = {
borderTop: "1px solid #eee",
textAlign: "center",
background: "#f8f8f8",
lineHeight: "28px"
};
return (
<div style={{ marginTop: 10 }}>
<Table
dataSource={this.state.dataSource}
hasHeader={false}
hasBorder={false}
>
<Table.Column title="Title" dataIndex="title" />
<Table.Column title="Time" dataIndex="time" width={200} />
</Table>
<p style={style} onClick={this.load.bind(this)}>
Load more data.
</p>
</div>
);
}
load() {
let { dataSource } = this.state;
dataSource = dataSource.concat(dataSource);
this.setState({ dataSource });
}
}
const getData = () => {
let result = [];
for (let i = 0; i < 5; i++) {
result.push({
title: `Quotation for 1PCS Nano ${3 + i}.0 controller compatible`,
id: 100306660940 + i,
time: 2000 + i,
children: [
{
title: `Sub title for Quotation ${3 + i}`,
time: 2000 + i
},
{
title: `Sub2 title for Quotation ${3 + i}`,
time: 2000 + i
}
]
});
}
return result;
},
render = (value, index, record) => {
return <a>Remove({record.id})</a>;
},
expandedRowRender = record => {
let children = record.children;
return <ExpandedApp dataSource={children} />;
};
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
dataSource: getData(),
hasBorder: false,
expandedRowKeys: []
};
}
render() {
const renderTitle = (value, index, record) => {
return (
<div>
{value}
<span onClick={this.toggleExpand.bind(this, record)}>+++++</span>
</div>
);
};
return (
<span>
<p>
{" "}
<Button onClick={this.disabledExpandedCol.bind(this)}>
{" "}
设置第4行禁用{" "}
</Button>{" "}
<Button onClick={this.toggleCol.bind(this)}> 隐藏+号 </Button>
</p>
<Table
dataSource={this.state.dataSource}
isZebra={this.state.isZebra}
hasBorder={this.state.hasBorder}
onSort={this.onSort.bind(this)}
expandedRowRender={expandedRowRender}
expandedRowIndent={[1, 1]}
expandedRowKeys={this.state.expandedRowKeys}
getExpandedColProps={this.state.getExpandedColProps}
hasExpandedRowCtrl={this.state.hasExpandedRowCtrl}
onExpandedChange={this.onExpandedChange.bind(this)}
>
<Table.Column title="Id" dataIndex="id" sortable />
<Table.Column title="Title" dataIndex="title" cell={renderTitle} />
<Table.Column title="Time" dataIndex="time" width={200} />
<Table.Column cell={render} width={200} />
</Table>
</span>
);
}
onSort(dataIndex, order) {
let dataSource = this.state.dataSource.sort(function(a, b) {
let result = a[dataIndex] - b[dataIndex];
return order === "asc" ? (result > 0 ? 1 : -1) : result > 0 ? -1 : 1;
});
this.setState({
dataSource
});
}
disabledExpandedCol() {
this.setState({
getExpandedColProps: (record, index) => {
if (index === 3) {
return {
disabled: true
};
}
}
});
}
toggleCol() {
this.setState({
hasExpandedRowCtrl: false
});
}
onExpandedChange(expandedRowKeys) {
this.setState({ expandedRowKeys });
}
toggleExpand(record) {
let key = record.id,
{ expandedRowKeys } = this.state,
index = expandedRowKeys.indexOf(key);
if (index > -1) {
expandedRowKeys.splice(index, 1);
} else {
expandedRowKeys.push(key);
}
this.setState({
expandedRowKeys: expandedRowKeys
});
}
}
ReactDOM.render(<App />, mountNode);
可以通过 expandedRowRender
额外渲染行
查看源码在线预览
import { Table, Button } from "@icedesign/base";
const getData = () => {
let result = [];
for (let i = 0; i < 5; i++) {
result.push({
title: `Quotation for 1PCS Nano ${3 + i}.0 controller compatible`,
id: 100306660940 + i,
time: 2000 + i
});
}
return result;
},
render = (value, index, record) => {
return <a>Remove({record.id})</a>;
};
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
dataSource: getData()
};
}
render() {
return (
<div>
<p>
<Button onClick={this.toggleIndent.bind(this)}>
{" "}
设置缩进为左二右一{" "}
</Button>
</p>
<Table
dataSource={this.state.dataSource}
isZebra={this.state.isZebra}
hasBorder={false}
onSort={this.onSort.bind(this)}
expandedRowRender={record => record.title}
onRowClick={() => console.log("rowClick")}
onExpandedRowClick={() => console.log("expandedRowClick")}
expandedRowIndent={this.state.expandedRowIndent}
>
<Table.Column title="Id" dataIndex="id" sortable />
<Table.Column title="Title" dataIndex="title" />
<Table.Column title="Time" dataIndex="time" />
<Table.Column cell={render} width={200} />
</Table>
</div>
);
}
onSort(dataIndex, order) {
let dataSource = this.state.dataSource.sort(function(a, b) {
let result = a[dataIndex] - b[dataIndex];
return order === "asc" ? (result > 0 ? 1 : -1) : result > 0 ? -1 : 1;
});
this.setState({
dataSource
});
}
toggleIndent() {
this.setState({
expandedRowIndent: [2, 1]
});
}
toggleCol() {
this.setState({
hasExpandedRowCtrl: false
});
}
}
ReactDOM.render(<App />, mountNode);
示例演示了排序和过滤的特性
查看源码在线预览
import { Table, Button } from "@icedesign/base";
const getData = () => {
let result = [];
for (let i = 0; i < 5; i++) {
result.push({
title: `Quotation for 1PCS Nano ${3 + i}.0 controller compatible`,
id: 100306660940 + i,
time: 2000 + i
});
}
return result;
},
render = (value, index, record) => {
return <a>Remove({record.id})</a>;
};
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
dataSource: getData(),
filterMode: "multiple"
};
}
render() {
let filters = [
{
label: "Nano 包含3",
value: 3
},
{
label: "Nano 包含2",
value: 2,
children: [
{
label: "Nano 包含12",
value: 22
},
{
label: "Nano 包含23",
value: 23
}
]
},
{
label: "其他",
children: [
{
label: "Nano 包含4",
value: 4
},
{
label: "Nano 包含5",
value: 5
}
]
}
];
return (
<div>
<p>
<Button onClick={this.changeMode.bind(this)}>
切换过滤为单选模式
</Button>
</p>
<Table
dataSource={this.state.dataSource}
onSort={this.onSort.bind(this)}
onFilter={this.onFilter.bind(this)}
>
<Table.Column title="Id" dataIndex="id" sortable />
<Table.Column
title="Title"
dataIndex="title"
filters={filters}
filterMode={this.state.filterMode}
/>
<Table.Column title="Time" dataIndex="time" />
<Table.Column cell={render} width={200} />
</Table>
</div>
);
}
onSort(dataIndex, order) {
let dataSource = this.state.dataSource.sort(function(a, b) {
let result = a[dataIndex] - b[dataIndex];
return order === "asc" ? (result > 0 ? 1 : -1) : result > 0 ? -1 : 1;
});
this.setState({
dataSource
});
}
onFilter(filterParams) {
let dataSource = getData();
for (let key in filterParams) {
let selectedKeys = filterParams[key].selectedKeys;
if (selectedKeys.length) {
dataSource = dataSource.filter(record => {
return selectedKeys.some(value => {
return record[key].indexOf(value) > -1;
});
});
}
}
this.setState({ dataSource });
}
changeMode() {
this.setState({
filterMode: "single"
});
}
}
ReactDOM.render(<App />, mountNode);
表格可以固定表头
查看源码在线预览
import { Table, Button } from "@icedesign/base";
const onRowClick = function(record, index, e) {
console.log(record, index, e);
},
getData = length => {
let result = [];
for (let i = 0; i < length; i++) {
result.push({
title: {
name: `Quotation for 1PCS Nano ${3 + i}.0 controller compatible`
},
id: 100306660940 + i,
time: 2000 + i
});
}
return result;
},
render = (value, index, record) => {
return <a>Remove({record.id})</a>;
};
class App extends React.Component {
state = {
dataSource: getData(10)
};
render() {
return (
<div>
<p>
<Button onClick={this.reduceContent.bind(this)}>切换到2条数据</Button>
</p>
<Table
dataSource={this.state.dataSource}
onRowClick={onRowClick}
fixedHeader
>
<Table.Column title="Id" dataIndex="id" />
<Table.Column title="Title" dataIndex="title.name" />
<Table.Column title="Time" dataIndex="time" />
<Table.Column cell={render} width={200} />
</Table>
</div>
);
}
reduceContent() {
this.setState({
dataSource: getData(2)
});
}
}
ReactDOM.render(<App />, mountNode);
分组列表展现
查看源码在线预览
import { Table, Button } from "@icedesign/base";
let dataSource = [
{
price: "US $2.45",
status: 0,
id: 1,
product: [
{
title:
"2014 New Fashion Novelty Tank Slim Women's Fashion Dresses With Lace",
avatar:
"https://sc01.alicdn.com/kf/HTB1ravHKXXXXXccXVXXq6xXFXXXJ/Chinese-Style-Fashion-Custom-Digital-Print-Silk.jpg_220x220.jpg"
}
],
children: [
{
price: "US $2.5",
status: 1,
id: 2,
product: [
{
title:
"Free shipping women Casual dresses lady dress plus size 2014",
avatar:
"https://sc02.alicdn.com/kf/HTB1efnNLVXXXXbtXpXXq6xXFXXXN/Light-100-acrylic-fashionabe-snood-shawl-weight.jpg_220x220.jpg"
}
]
},
{
price: "US $2.5",
status: 1,
id: 3,
product: [
{
title:
"Free shipping women Casual dresses lady dress plus size 2014",
avatar:
"https://sc02.alicdn.com/kf/HTB1efnNLVXXXXbtXpXXq6xXFXXXN/Light-100-acrylic-fashionabe-snood-shawl-weight.jpg_220x220.jpg"
}
]
}
]
},
{
price: "US $2.5",
status: 1,
id: 4,
product: [
{
title: "Free shipping women Casual dresses lady dress plus size 2014",
avatar:
"https://sc02.alicdn.com/kf/HTB1efnNLVXXXXbtXpXXq6xXFXXXN/Light-100-acrylic-fashionabe-snood-shawl-weight.jpg_220x220.jpg"
}
]
}
],
productRender = function(product) {
return (
<div className="media">
<img src={product[0].avatar} className="media-side" />
<div className="media-content">{product[0].title}</div>
</div>
);
},
priceRender = function(price) {
return <b>{price}</b>;
},
statusRender = function(status) {
if (status) {
return "Already Priced";
} else {
return "No Priced";
}
},
operRender = function() {
return <a href="javascript:;">View</a>;
},
groupHeaderRender = function(record) {
return <div>{record.product[0].title}</div>;
},
getRowClassName = function(record) {
if (record.status === 0) {
return "highlight-row";
}
},
rowSelection = {
onChange: function(selectedKeys) {
console.log(selectedKeys);
}
};
class App extends React.Component {
state = {
hasSelection: false
};
render() {
return (
<div>
<p>
<Button onClick={this.toggleGroupSelection}>
Toggle GroupHeader Selection
</Button>
</p>
<Table
dataSource={dataSource}
getCellProps={(rowIndex, colIndex) => {
if (
(colIndex === 3 && rowIndex === 1) ||
(colIndex === 4 && rowIndex === 1)
) {
return {
colSpan: 1,
rowSpan: 2
};
}
}}
getRowClassName={getRowClassName}
rowSelection={rowSelection}
>
<Table.GroupHeader
cell={groupHeaderRender}
hasSelection={this.state.hasSelection}
/>
<Table.Column
cell={productRender}
title="Product Details"
dataIndex="product"
/>
<Table.Column
cell={priceRender}
title="Price"
dataIndex="price"
width={120}
/>
<Table.Column
cell={statusRender}
title="Status"
dataIndex="status"
width={100}
/>
<Table.Column cell={operRender} title="" width={100} />
</Table>
</div>
);
}
toggleGroupSelection = () => {
this.setState({
hasSelection: !this.state.hasSelection
});
};
}
ReactDOM.render(<App />, mountNode);
.media-side{
width:48px;
height:48px;
float:left;
margin-right:10px;
}
.media-content{
overflow: hidden;
vertical-align: top;
}
.media{
overflow: hidden;
}
.next-table .highlight-row .next-table-group-header td{
background: #E8F6FF;
}
.next-table .highlight-row td{
border-color: #D3E9F7;
}
演示表格锁列的功能
查看源码在线预览
import { Table, Button } from "@icedesign/base";
const onRowClick = function(record, index, e) {
console.log(record, index, e);
},
getData = () => {
let result = [];
for (let i = 0; i < 100; i++) {
result.push({
title: {
name: `Quotation for 1PCS Nano ${3 + i}.0 controller compatible`
},
id: 100306660940 + i,
time: 2000 + i
});
}
return result;
},
render = (value, index, record) => {
return <a>Remove({record.id})</a>;
};
class App extends React.Component {
state = {
dataSource: [],
cols: [
<Table.Column
title="Title"
dataIndex="title.name"
width={400}
key="name1"
lock
/>,
<Table.ColumnGroup title="abc" key="name-group">
<Table.Column
title="Title"
dataIndex="title.name"
width={100}
key="name2"
/>
<Table.Column
title="Title"
dataIndex="title.name"
width={400}
key="name3"
/>
</Table.ColumnGroup>,
<Table.Column title="Time" dataIndex="time" width={500} key="time" />
],
isLoading: true
};
render() {
let filters = [
{
label: "Nano 包含3",
value: 3
},
{
label: "Nano 包含2",
value: 2,
children: [
{
label: "Nano 包含12",
value: 22
},
{
label: "Nano 包含23",
value: 23
}
]
},
{
label: "其他",
children: [
{
label: "Nano 包含4",
value: 4
},
{
label: "Nano 包含5",
value: 5
}
]
}
];
return (
<div>
<p>
<Button onClick={this.reduceCol}>Reduce Cols</Button>
</p>
<Table
dataSource={this.state.dataSource}
onRowClick={onRowClick}
fixedHeader
isLoading={this.state.isLoading}
>
<Table.Column
title="Id-Id-Id-Id-Id-Id-Id-Id-Id-Id-Id-Id"
dataIndex="id"
lock
width={140}
filters={filters}
/>
{this.state.cols}
<Table.Column cell={render} width={200} lock="right" />
</Table>
</div>
);
}
componentDidMount() {
setTimeout(() => {
this.setState({
dataSource: getData(),
isLoading: false
});
}, 200);
}
reduceCol = () => {
this.setState({
cols: [
<Table.Column
title="Title"
dataIndex="title.name"
width={400}
key="name1"
lock
/>,
<Table.Column title="Time" dataIndex="time" width={100} key="time" />
]
});
};
}
ReactDOM.render(<App />, mountNode);
演示了tree模式和rowSelection模式混合
查看源码在线预览
import { Table } from "@icedesign/base";
const data = [
{
key: 1,
name: "a",
age: 32,
address: "我是a",
children: [
{
key: 11,
name: "aa",
age: 33,
address: "我是aa"
},
{
key: 12,
name: "ab",
age: 33,
address: "我是ab",
children: [
{
key: 121,
name: "aba",
age: 33,
address: "我是aba"
}
]
},
{
key: 13,
name: "ac",
age: 33,
address: "我是ac",
children: [
{
key: 131,
name: "aca",
age: 33,
address: "我是aca",
children: [
{
key: 1311,
name: "acaa",
age: 33,
address: "我是acaa"
},
{
key: 1312,
name: "acab",
age: 33,
address: "我是acab"
}
]
}
]
}
]
},
{
key: 2,
name: "b",
age: 32,
address: "我是b",
children: []
}
];
const tableMixTree = (
<Table
dataSource={data}
primaryKey="key"
isTree
rowSelection={{ onChange: () => {} }}
>
<Table.Column title="Key" dataIndex="key" />
<Table.Column title="Name" dataIndex="name" />
<Table.Column title="Age" dataIndex="age" />
<Table.Column title="Address" dataIndex="address" />
</Table>
);
const tableMixExpanded = (
<Table
dataSource={data}
primaryKey="key"
expandedRowRender={record => record.address}
rowSelection={{ onChange: () => {} }}
>
<Table.Column title="Key" dataIndex="key" />
<Table.Column title="Name" dataIndex="name" />
<Table.Column title="Age" dataIndex="age" />
<Table.Column title="Address" dataIndex="address" />
</Table>
);
const tableMixSelectionTreeLock = (
<div style={{ width: "500px" }}>
<Table
dataSource={data}
primaryKey="key"
rowSelection={{ onChange: () => {} }}
isTree
>
<Table.Column title="Key" dataIndex="key" width={100} />
<Table.Column title="Name" dataIndex="name" lock width={100} />
<Table.Column title="Age" dataIndex="age" width={200} lock="right" />
<Table.Column title="Address" dataIndex="address" width={200} />
</Table>
</div>
);
const tableMixLock = (
<div style={{ width: "500px" }}>
<Table
dataSource={data}
primaryKey="key"
rowSelection={{ onChange: () => {} }}
>
<Table.Column title="Key" dataIndex="key" width={100} />
<Table.Column title="Name" dataIndex="name" lock width={100} />
<Table.Column title="Age" dataIndex="age" width={200} lock="right" />
<Table.Column title="Address" dataIndex="address" width={200} />
</Table>
</div>
);
const tableMixExpandedLock = (
<div style={{ width: "500px" }}>
<Table
dataSource={data}
primaryKey="key"
rowSelection={{ onChange: () => {} }}
expandedRowRender={record => record.address}
expandedRowIndent={[3, 0]}
>
<Table.Column title="Key" dataIndex="key" width={100} />
<Table.Column title="Name" dataIndex="name" lock width={100} />
<Table.Column title="Age" dataIndex="age" width={200} lock="right" />
<Table.Column title="Address" dataIndex="address" width={200} />
</Table>
</div>
);
const tableMixTreeLock = (
<div style={{ width: "500px" }}>
<Table dataSource={data} primaryKey="key" isTree>
<Table.Column title="Key" dataIndex="key" width={100} />
<Table.Column title="Name" dataIndex="name" lock width={100} />
<Table.Column title="Age" dataIndex="age" width={200} lock="right" />
<Table.Column title="Address" dataIndex="address" width={200} />
</Table>
</div>
);
ReactDOM.render(
<div className="mix-demo">
<div className="row">
<h4>tree和选择混合</h4>
{tableMixTree}
</div>
<div className="row">
<h4>额外渲染和选择混合</h4>
{tableMixExpanded}
</div>
<div className="row">
<h4>tree和锁列和选择混合</h4>
{tableMixSelectionTreeLock}
</div>
<div className="row">
<h4>额外渲染列和锁列和选择混合</h4>
{tableMixExpandedLock}
</div>
<div className="row">
<h4>锁列和选择混合</h4>
{tableMixLock}
</div>
<div className="row">
<h4>tree和锁列混合</h4>
{tableMixTreeLock}
</div>
</div>,
mountNode
);
.mix-demo .row {
margin-top:10px;
}
多个表头
查看源码在线预览
import { Table, Button } from "@icedesign/base";
const onRowClick = function(record, index, e) {
console.log(record, index, e);
},
getData = j => {
let result = [];
for (let i = 0; i < j; i++) {
result.push({
title: {
name: `Quotation for 1PCS Nano ${3 + i}.0 controller compatible`
},
id: 100306660940 + i,
time: 2000 + i
});
}
return result;
},
render = (value, index, record) => {
return <a>Remove({record.id})</a>;
};
class App extends React.Component {
state = {
dataSource: getData(15)
};
render() {
return (
<div>
<p>
<Button onClick={this.onClick}>Reduce count</Button>
</p>
<Table
dataSource={this.state.dataSource}
onRowClick={onRowClick}
fixedHeader
maxBodyHeight={400}
>
<Table.Column title="Id1" dataIndex="id" width={140} />
<Table.ColumnGroup>
<Table.Column title="Id2" dataIndex="id" lock width={140} />
<Table.Column title="Title" dataIndex="title.name" width={400} />
<Table.Column title="Title" dataIndex="title.name" width={200} />
</Table.ColumnGroup>
<Table.ColumnGroup>
<Table.Column title="Time" dataIndex="time" width={500} />
<Table.Column cell={render} width={200} lock="right" />
</Table.ColumnGroup>
</Table>
</div>
);
}
onClick = () => {
this.setState({
dataSource: getData(4)
});
};
}
ReactDOM.render(<App />, mountNode);
通过getProps来控制选择框属性
查看源码在线预览
import { Table } from "@icedesign/base";
const onChange = function(...args) {
console.log(...args);
},
getData = () => {
let result = [];
for (let i = 0; i < 5; i++) {
result.push({
title: {
name: `Quotation for 1PCS Nano ${3 + i}.0 controller compatible`
},
id: 100306660940 + i,
time: 2000 + i
});
}
return result;
},
render = (value, index, record) => {
return <a>Remove({record.id})</a>;
},
rowSelection = {
onChange: onChange,
getProps: record => {
return {
disabled: record.id === 100306660942
};
}
};
ReactDOM.render(
<Table dataSource={getData()} rowSelection={rowSelection}>
<Table.Column title="Id" dataIndex="id" />
<Table.Column title="Title" dataIndex="title.name" />
<Table.Column title="Time" dataIndex="time" />
<Table.Column cell={render} width={200} />
</Table>,
mountNode
);
表格可选择功能
查看源码在线预览
import { Table } from "@icedesign/base";
const onChange = function(...args) {
console.log(...args);
},
getData = () => {
let result = [];
for (let i = 0; i < 5; i++) {
result.push({
title: {
name: `Quotation for 1PCS Nano ${3 + i}.0 controller compatible`
},
id: 100306660940 + i,
time: 2000 + i
});
}
return result;
},
render = (value, index, record) => {
return <a>Remove({record.id})</a>;
};
ReactDOM.render(
<Table dataSource={getData()} rowSelection={{ onChange: onChange }}>
<Table.Column title="Id" dataIndex="id" />
<Table.Column title="Title" dataIndex="title.name" />
<Table.Column title="Time" dataIndex="time" />
<Table.Column cell={render} width={200} />
</Table>,
mountNode
);
自定义表格边框
查看源码在线预览
import { Table, Button } from "@icedesign/base";
const getData = () => {
let result = [];
for (let i = 0; i < 5; i++) {
result.push({
title: `Quotation for 1PCS Nano ${3 + i}.0 controller compatible`,
id: 100306660940 + i,
time: 2000 + i
});
}
return result;
},
render = (value, index, record) => {
return <a>Remove({record.id})</a>;
};
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
dataSource: getData(),
className: "",
align: "left"
};
}
render() {
return (
<span>
<p>
<Button onClick={this.toggleZebra.bind(this)}> Toggle zebra </Button>{" "}
<Button onClick={this.toggleBorder.bind(this)}>
{" "}
Toggle border
</Button>{" "}
<Button onClick={this.makeBeauty.bind(this)}>
{" "}
Make second column beauty{" "}
</Button>{" "}
<Button onClick={this.makeAlign.bind(this)}>
{" "}
Make first column align right{" "}
</Button>{" "}
</p>
<Table
dataSource={this.state.dataSource}
isZebra={this.state.isZebra}
hasBorder={this.state.hasBorder}
onSort={this.onSort.bind(this)}
>
<Table.Column
title="Id"
dataIndex="id"
sortable
align={this.state.align}
/>
<Table.Column
title="Title"
dataIndex="title"
className={this.state.className}
/>
<Table.Column title="Time" dataIndex="time" />
<Table.Column cell={render} width={200} />
</Table>
</span>
);
}
onSort(dataIndex, order) {
let dataSource = this.state.dataSource.sort(function(a, b) {
let result = a[dataIndex] - b[dataIndex];
return order === "asc" ? (result > 0 ? 1 : -1) : result > 0 ? -1 : 1;
});
this.setState({
dataSource
});
}
toggleZebra() {
this.setState({
isZebra: !this.state.isZebra
});
}
toggleBorder() {
this.setState({
hasBorder: !this.state.hasBorder
});
}
makeBeauty() {
this.setState({
className: "beauty"
});
}
makeAlign() {
this.setState({
align: "right"
});
}
}
ReactDOM.render(<App />, mountNode);
.beauty{
background: #f7f7f7;
}