Table 表格

展示行列数据。

何时使用

  • 当有大量结构化的数据需要展现时;
  • 当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时。

如何使用

Table 有两种模式,本地数据和远程数据模式。

本地数据模式是指数据一次性载入内存,纯前端进行分页、筛选、排序等功能。

通过指定表格的数据源 dataSource 为一个数据数组。

var dataSource = [{
  key: '1',
  name: '胡彦斌',
  age: 32,
  address: '西湖区湖底公园1号'
}, {
  key: '2',
  name: '胡彦祖',
  age: 42,
  address: '西湖区湖底公园1号'
}];

<Table dataSource={dataSource} />

远程数据模式是更常见的业务场景,是一次只从服务端读取一页的数据放在前端,执行筛选、排序、切换页码等操作时均向后台发送请求,后台返回当页的数据和相关分页信息。

通过指定表格的数据源 dataSource 为一个 DataSource 的实例如下。

var dataSource = new Table.DataSource({
  url: '/api/users',
  resolve: function(result) {
    return result.data;
  },
  getPagination: function(result) {},
  getParams: function(pagination, filters, sorter) {}
});

<Table dataSource={dataSource} />

API

Table

参数 说明 类型 可选值 默认值
rowSelection 列表项是否可选择 Object false
pagination 分页器 Object 配置项参考 pagination,设为 false 时不显示分页
size 正常或迷你类型 String normal or small normal
dataSource 数据源,可以为数组(本地模式)或一个数据源描述对象(远程模式) Array or Object
columns 表格列的配置描述,具体项见下表 Array
rowKey 表格列 key 的取值 Function(recode,index):string record.key
expandIconAsCell 设置展开 Icon 是否单独一列 Boolean true

Column

列描述数据对象,是 columns 中的一项。

参数 说明 类型 可选值 默认值
title 列头显示文字 String or React.Element
dataIndex 列数据在 data 中对应的 key React.Element
key React 需要的 key String
render 生成复杂数据的渲染函数,参数分别为当前列的值,当前列数据,列索引 Function(text, record, index) {}
filters 表头的筛选菜单项 Array
onFilter 本地模式下,确定筛选的运行函数 Function
sorter 排序函数,本地模式下为一个函数,远程模式下为布尔值 Function or Boolean
width 列宽度 String or Number

dataSource

远程数据源配置对象。

参数 说明 类型 可选值 默认值
url 数据源地址 String
resolve 获得数据的解析函数,接收参数为远程数据返回的 result Function
getPagination 和后台接口返回的分页数据进行适配的函数,返回值会传给表格中的分页器 Function
getParams 和后台接口接收的参数进行适配,返回值会作为请求的参数发送 Function

组件演示

var Table = antd.Table;
var columns = [{
  title: '姓名',
  dataIndex: 'name',
  render: function(text) {
    return <a href="javascript:;">{text}</a>;
  }
}, {
  title: '年龄',
  dataIndex: 'age'
}, {
  title: '住址',
  dataIndex: 'address'
}, {
  title: '操作',
  dataIndex: '',
  render: function(text, record) {
    return <span>
      <a href="javascript:;">操作一</a>
      <span className="ant-divider"></span>
      <a href="javascript:;">操作二</a>
      <span className="ant-divider"></span>
      <a href="javascript:;" className="ant-dropdown-link">
        更多 <i className="anticon anticon-down"></i>
      </a>
    </span>;
  }
}];
var data = [{
  key: '1',
  name: '胡彦斌',
  age: 32,
  address: '西湖区湖底公园1号'
}, {
  key: '2',
  name: '胡彦祖',
  age: 42,
  address: '西湖区湖底公园1号'
}, {
  key: '3',
  name: '李大嘴',
  age: 32,
  address: '西湖区湖底公园1号'
}];

React.render(<Table columns={columns} dataSource={data} />
, document.getElementById('components-table-demo-basic'));

简单的表格,最后一列是各种操作。

var Table = antd.Table;
var columns = [{
  title: '姓名',
  dataIndex: 'name',
  render: function(text) {
    return <a href="javascript:;">{text}</a>;
  }
}, {
  title: '年龄',
  dataIndex: 'age'
}, {
  title: '住址',
  dataIndex: 'address'
}];
var data = [{
  key: '1',
  name: '胡彦斌',
  age: 32,
  address: '西湖区湖底公园1号'
}, {
  key: '2',
  name: '胡彦祖',
  age: 42,
  address: '西湖区湖底公园1号'
}, {
  key: '3',
  name: '李大嘴',
  age: 32,
  address: '西湖区湖底公园1号'
}];

// 通过 rowSelection 对象表明需要行选择
var rowSelection = {
  onSelect: function(record, selected, selectedRows) {
    console.log(record, selected, selectedRows);
  },
  onSelectAll: function(selected, selectedRows) {
    console.log(selected, selectedRows);
  }
};

React.render(<Table rowSelection={rowSelection} columns={columns} dataSource={data} />
, document.getElementById('components-table-demo-row-selection'));

第一列是联动的选择框。

var Table = antd.Table;

var columns = [{
  title: '姓名',
  dataIndex: 'name',
  render: function(text) {
    return <a href="javascript:;">{text}</a>;
  }
}, {
  title: '年龄',
  dataIndex: 'age'
}, {
  title: '住址',
  dataIndex: 'address'
}];
var data = [];

for (let i=0; i<46; i++) {
  data.push({
    key: i,
    name: '李大嘴' + i,
    age: 32,
    address: '西湖区湖底公园' + i + '号'
  });
}

var pagination = {
  total: data.length,
  current: 2,
  showSizeChanger: true
};

React.render(<Table columns={columns} dataSource={data} pagination={pagination} />
, document.getElementById('components-table-demo-paging'));

数据项较多时显示分页。

var Table = antd.Table;
var columns = [{
  title: '姓名',
  dataIndex: 'name',
  filters: [{
    text: '姓李的',
    value: '李'
  }, {
    text: '姓胡的',
    value: '胡'
  }],
  // 指定确定筛选的条件函数
  // 这里是名字中第一个字是 value
  onFilter: function(value, record) {
    return record.name.indexOf(value) === 0;
  },
  sorter: function(a, b) {
    return a.name.length - b.name.length;
  }
}, {
  title: '年龄',
  dataIndex: 'age',
  sorter: function(a, b) {
    return a.age - b.age;
  }
}, {
  title: '地址',
  dataIndex: 'address',
  sorter: function(a, b) {
    return a.address.length - b.address.length;
  }
}];

var data = [{
  key: '1',
  name: '胡斌',
  age: 32,
  address: '西湖区湖底公园1号'
}, {
  key: '2',
  name: '胡彦祖',
  age: 42,
  address: '西湖区湖底公园12号'
}, {
  key: '3',
  name: '李大嘴',
  age: 32,
  address: '西湖区湖底公园123号'
}, {
  key: '4',
  name: '李秀莲大嘴哥',
  age: 32,
  address: '西湖区湖底公园123号'
}];

React.render(<Table columns={columns} dataSource={data} />
, document.getElementById('components-table-demo-head'));

对某一列数据进行筛选,使用列的 filter 属性来指定筛选的列表。

对某一列数据进行排序,通过指定列的 sorter 函数即可启动排序按钮。sorter: function(a, b) { ... }, a、b 为比较的两个列数据。

var Table = antd.Table;

var columns = [{
  title: '姓名',
  dataIndex: 'name',
  filters: [{
    text: '姓李的',
    value: '李'
  }, {
    text: '姓胡的',
    value: '胡'
  }]
}, {
  title: '年龄',
  dataIndex: 'age',
  sorter: true
}, {
  title: '住址',
  dataIndex: 'address'
}];

var dataSource = new Table.DataSource({
  url: "/components/table/demo/data.json",
  resolve: function(result) {
    return result.data;
  },
  data: {},
  // 和后台接口返回的分页数据进行适配
  getPagination: function(result) {
    return {
      total: result.totalCount,
      pageSize: result.pageSize
    }
  },
  // 和后台接口接收的参数进行适配
  // 参数里提供了分页、筛选、排序的信息
  getParams: function(pagination, filters, sorter) {
    console.log('getParams 的参数是:', pagination, filters, sorter);
    var params = {
      pageSize: pagination.pageSize,
      currentPage: pagination.current,
      sortField: sorter.field,
      sortOrder: sorter.order
    };
    for (var key in filters) {
      params[key] = filters[key];
    }
    console.log('请求参数:', params);
    return params;
  }
});

var Test = React.createClass({
  getInitialState() {
    return {
      dataSource: dataSource
    };
  },
  refresh() {
    this.setState({
      dataSource: dataSource.clone()
    });
  },
  changeAndRefresh() {
    // 可以修改原来的 dataSource 再发请求
    this.setState({
      dataSource: dataSource.clone({
        data: {
          city: 'hz'
        }
      })
    });
  },
  render() {
    return <div>
      <Table columns={columns} dataSource={this.state.dataSource} />
      <button className="ant-btn ant-btn-primary" onClick={this.refresh}>
        重新加载数据
      </button>
      &nbsp;
      <button className="ant-btn" onClick={this.changeAndRefresh}>
        加载 city=hz 的数据
      </button>
    </div>;
  }
});

React.render(<Test />, document.getElementById('components-table-demo-ajax'));

远程读取的表格是更为常见的模式,下面的表格使用了 dataSource 对象和远程数据源绑定和适配,并具有筛选、排序等功能以及页面 loading 效果。

注意,此示例是静态数据模拟,数据并不准确,请打开网络面板查看请求。

var Table = antd.Table;
var columns = [{
  title: '姓名',
  dataIndex: 'name'
}, {
  title: '年龄',
  dataIndex: 'age'
}, {
  title: '住址',
  dataIndex: 'address'
}];

var data = [{
  key: '1',
  name: '胡彦斌',
  age: 32,
  address: '西湖区湖底公园1号'
}, {
  key: '2',
  name: '胡彦祖',
  age: 42,
  address: '西湖区湖底公园1号'
}, {
  key: '3',
  name: '李大嘴',
  age: 32,
  address: '西湖区湖底公园1号'
}];

React.render(<Table columns={columns} dataSource={data} pagination={false} />
, document.getElementById('components-table-demo-nopagination'));

传入 pagination 为 false 即可。

var Table = antd.Table;
var columns = [{
  title: '姓名',
  dataIndex: 'name'
}, {
  title: '年龄',
  dataIndex: 'age'
}, {
  title: '住址',
  dataIndex: 'address'
}];
var data = [{
  key: '1',
  name: '胡彦斌',
  age: 32,
  address: '西湖区湖底公园1号'
}, {
  key: '2',
  name: '胡彦祖',
  age: 42,
  address: '西湖区湖底公园1号'
}, {
  key: '3',
  name: '李大嘴',
  age: 32,
  address: '西湖区湖底公园1号'
}];

React.render(<Table columns={columns} dataSource={data} size="small" />
, document.getElementById('components-table-demo-small'));

size="small", 用在对话框等空间较小的地方。

var Table = antd.Table;
var columns = [{
  title: '姓名',
  dataIndex: 'name',
  render: function(text) {
    return <a href="javascript:;">{text}</a>;
  }
}, {
  title: '年龄',
  dataIndex: 'age'
}, {
  title: '住址',
  dataIndex: 'address'
}];

var data = [{
  key: '1',
  name: '胡彦斌',
  age: 32,
  address: '西湖区湖底公园1号'
}, {
  key: '2',
  name: '胡彦祖',
  age: 42,
  address: '西湖区湖底公园1号'
}, {
  key: '3',
  name: '李大嘴',
  age: 32,
  address: '西湖区湖底公园1号'
}];

React.render(<Table columns={columns} dataSource={data} bordered={true} />
, document.getElementById('components-table-demo-bordered'));

添加表格边框线,bordered={true}

var Table = antd.Table;
var columns = [{
  title: '姓名',
  dataIndex: 'name',
  render: function(text) {
    return <a href="javascript:;">{text}</a>;
  }
}, {
  title: '年龄',
  dataIndex: 'age'
}, {
  title: '住址',
  dataIndex: 'address'
}];
var data1 = [{
  key: '1',
  name: '胡彦斌',
  age: 32,
  address: '西湖区湖底公园1号'
}, {
  key: '2',
  name: '胡彦祖',
  age: 42,
  address: '西湖区湖底公园1号'
}, {
  key: '3',
  name: '李大嘴',
  age: 32,
  address: '西湖区湖底公园1号'
}];
var data2 = [{
  key: '11',
  name: '胡彦斌2',
  age: 32,
  address: '西湖区湖底公园2号'
}, {
  key: '22',
  name: '胡彦祖2',
  age: 42,
  address: '西湖区湖底公园2号'
}, {
  key: '33',
  name: '李大嘴2',
  age: 32,
  address: '西湖区湖底公园2号'
}];

var App = React.createClass({
  getInitialState() {
    return {
      data: []
    };
  },
  handleClick1() {
    this.setState({
      data: data1
    });
  },
  handleClick2() {
    this.setState({
      data: data2
    });
  },
  render() {
    return <div>
      <Table columns={columns} dataSource={this.state.data} />
      <button className="ant-btn" onClick={this.handleClick1}>加载本地数据1</button>
      &nbsp;
      <button className="ant-btn" onClick={this.handleClick2}>加载本地数据2</button>
    </div>;
  }
})

React.render(<App />
, document.getElementById('components-table-demo-local-data'));

由父元素控制自身数据展示。

var Table = antd.Table;

function renderAction() {
  return <a href="javascript:;">删除</a>;
}

function expandedRowRender(record) {
  return <p>{record.description}</p>;
}

var columns = [
  {title: '姓名', dataIndex: 'name', key: 'name'},
  {title: '年龄', dataIndex: 'age', key: 'age'},
  {title: '住址', dataIndex: 'address', key: 'address'},
  {title: '操作', dataIndex: '', key: 'x', render: renderAction}
];

var data = [
  {name: '胡彦斌', age: 32, address: '西湖区湖底公园1号', description: '我是胡彦斌,今年32岁,住在西湖区湖底公园1号。'},
  {name: '吴彦祖', age: 42, address: '西湖区湖底公园2号', description: '我是吴彦祖,今年42岁,住在西湖区湖底公园2号。'},
  {name: '李大嘴', age: 32, address: '西湖区湖底公园3号', description: '我是李大嘴,今年32岁,住在西湖区湖底公园3号。'}
];

React.render(
<Table columns={columns}
  expandedRowRender={expandedRowRender}
  dataSource={data}
  className="table" />
, document.getElementById('components-table-demo-expand'));

当表格内容较多不能一次性完全展示时。