From 62d4bbd5739698761d540b100f75b8ce9ade6a4f Mon Sep 17 00:00:00 2001 From: afc163 Date: Wed, 9 Dec 2015 21:49:32 +0800 Subject: [PATCH 1/3] remove remote dataSource --- components/table/demo/ajax.md | 113 +++++++---------- components/table/demo/nopagination.md | 2 +- components/table/demo/paging.md | 2 +- components/table/index.jsx | 167 +++++--------------------- components/table/index.md | 55 +++------ package.json | 2 +- scripts/demo.js | 1 + 7 files changed, 94 insertions(+), 248 deletions(-) diff --git a/components/table/demo/ajax.md b/components/table/demo/ajax.md index c6ac0b8aa8..66a7fa3c6b 100644 --- a/components/table/demo/ajax.md +++ b/components/table/demo/ajax.md @@ -1,15 +1,20 @@ -# 动态加载数据 +# 远程加载数据 - order: 7 -远程读取的表格是**更为常见的模式**,下面的表格使用了 `dataSource` 对象和远程数据源绑定和适配,并具有筛选、排序等功能以及页面 loading 效果。 +在 `0.11.0` 以后,`dataSource` 远程模式被移除,用户可以自行实现数据读取方式。 -**注意,此示例是静态数据模拟,数据并不准确,请打开网络面板查看请求。** +这个例子通过简单的 ajax 读取方式,演示了如何从服务端读取并展现数据,具有筛选、排序等功能以及页面 loading 效果。开发者可以自行接入其他数据处理方式。 + +另外,本例也展示了筛选排序功能如何交给服务端实现,列不需要指定具体的 `onFilter` 和 `sorter` 函数,而是在把筛选和排序的参数发到服务端来处理。 + +**注意,此示例是静态数据模拟,展示数据不会变化,请打开网络面板查看请求。** --- ````jsx -import { Table, Button } from 'antd'; +import { Table } from 'antd'; +import reqwest from 'reqwest'; const columns = [{ title: '姓名', @@ -30,23 +35,20 @@ const columns = [{ dataIndex: 'address' }]; -const dataSource = new Table.DataSource({ - url: '/components/table/demo/data.json', - resolve: function(result) { - return result.data; - }, - data: {}, - // 和后台接口返回的分页数据进行适配 - getPagination: function(result) { +const Test = React.createClass({ + getInitialState() { return { - total: result.totalCount, - pageSize: result.pageSize + data: [], + pagination: {}, + loading: false, }; }, - // 和后台接口接收的参数进行适配 - // 参数里提供了分页、筛选、排序的信息 - getParams: function(pagination, filters, sorter) { - console.log('getParams 的参数是:', pagination, filters, sorter); + handleTableChange(pagination, filters, sorter) { + const pager = this.state.pagination; + pager.current = pagination.current; + this.setState({ + pagination: pager + }); const params = { pageSize: pagination.pageSize, currentPage: pagination.current, @@ -56,61 +58,38 @@ const dataSource = new Table.DataSource({ for (let key in filters) { params[key] = filters[key]; } + this.fetch(params); + }, + fetch(params = {}) { console.log('请求参数:', params); - return params; - } -}); - -const Test = React.createClass({ - getInitialState() { - return { - dataSource: null, - pagination: { - onChange: this.hanlePageChange + this.setState({ loading: true }); + reqwest({ + url: 'demo/data.json', + method: 'get', + data: params, + type: 'json', + success: (result) => { + const pagination = this.state.pagination; + pagination.total = result.totalCount; + this.setState({ + loading: false, + data: result.data, + pagination, + }); } - }; - }, - hanlePageChange(page) { - // 使用受控属性 current,方便外部设置页数 - const pagination = this.state.pagination; - pagination.current = page; - this.setState({ - pagination, - dataSource: dataSource.clone(), }); }, - refresh() { - // 回到第一页 - const pagination = this.state.pagination; - pagination.current = 1; - this.setState({ - pagination, - dataSource: dataSource.clone(), - }); - }, - changeAndRefresh() { - // 回到第一页 - const pagination = this.state.pagination; - pagination.current = 1; - // 可以修改原来的 dataSource 再发请求 - this.setState({ - pagination, - dataSource: dataSource.clone({ - data: { city: 'hz' } - }), - }); + componentDidMount() { + this.fetch(); }, render() { - return
- - -   - - ; + return ( +
+ ); } }); diff --git a/components/table/demo/nopagination.md b/components/table/demo/nopagination.md index d681204215..f4b567c88b 100644 --- a/components/table/demo/nopagination.md +++ b/components/table/demo/nopagination.md @@ -2,7 +2,7 @@ - order: 8 -传入 pagination 为 false 即可。 +传入 pagination 为 false 即可。此时表格将完整显示 dataSource 内的数据,不进行任何分页。 --- diff --git a/components/table/demo/paging.md b/components/table/demo/paging.md index 76655dae2b..a6a92123be 100644 --- a/components/table/demo/paging.md +++ b/components/table/demo/paging.md @@ -35,7 +35,7 @@ for (let i = 0; i < 46; i++) { const pagination = { total: data.length, - current: 2, + current: 1, showSizeChanger: true }; diff --git a/components/table/index.jsx b/components/table/index.jsx index 4da74854d5..93131acff4 100644 --- a/components/table/index.jsx +++ b/components/table/index.jsx @@ -1,5 +1,4 @@ import React from 'react'; -import reqwest from 'reqwest'; import Table from 'rc-table'; import Checkbox from '../checkbox'; import Radio from '../radio'; @@ -13,49 +12,20 @@ import classNames from 'classnames'; function noop() { } -function defaultResolve(data) { - return data || []; -} - const defaultLocale = { filterTitle: '筛选', filterConfirm: '确定', filterReset: '重置' }; -class DataSource { - init(config) { - this.config = config; - this.url = config.url || ''; - this.resolve = config.resolve || defaultResolve; - this.getParams = config.getParams || noop; - this.getPagination = config.getPagination || noop; - this.headers = config.headers || {}; - this.data = config.data || {}; - } - - constructor(config) { - if (config) { - this.init(config); - } - } - - clone(config = {}) { - return new DataSource(objectAssign({}, this.config, config)); - } -} - let AntTable = React.createClass({ getInitialState() { return { // 减少状态 selectedRowKeys: [], - // only for remote - data: [], dataSource: this.props.dataSource, filters: {}, selectionDirty: false, - loading: this.props.loading, sortColumn: '', sortOrder: '', sorter: null, @@ -82,7 +52,7 @@ let AntTable = React.createClass({ }, propTypes: { - dataSource: React.PropTypes.oneOfType([React.PropTypes.array, React.PropTypes.instanceOf(DataSource)]) + dataSource: React.PropTypes.array, }, getDefaultSelection() { @@ -112,42 +82,23 @@ let AntTable = React.createClass({ nextProps.dataSource !== this.props.dataSource) { let selectedRowKeys = this.state.selectedRowKeys; // 把不在当前页的选中项去掉 - if (this.isLocalDataSource()) { - let currentPageRowKeys = - this.getLocalDataPaging(nextProps.dataSource).map( - (record, i) => this.getRecordKey(record, i) - ); - selectedRowKeys = selectedRowKeys.filter((key) => { - return currentPageRowKeys.indexOf(key) >= 0; - }); - } + let currentPageRowKeys = + this.getCurrentPageData(nextProps.dataSource).map( + (record, i) => this.getRecordKey(record, i) + ); + selectedRowKeys = selectedRowKeys.filter((key) => { + return currentPageRowKeys.indexOf(key) >= 0; + }); this.setState({ selectionDirty: false, selectedRowKeys, dataSource: nextProps.dataSource, - loading: true - }, this.fetch); - } - if ('loading' in nextProps) { - this.setState({ - loading: nextProps.loading }); } }, hasPagination(pagination) { - if (pagination === undefined) { - pagination = this.props.pagination; - } - return pagination !== false; - }, - - isLocalDataSource() { - return Array.isArray(this.state.dataSource); - }, - - getRemoteDataSource() { - return this.state.dataSource; + return this.props.pagination !== false; }, toggleSortOrder(order, column) { @@ -167,7 +118,7 @@ let AntTable = React.createClass({ sortOrder = order; } } - if (this.isLocalDataSource()) { + if (typeof column.sorter === 'function') { sorter = function () { let result = column.sorter.apply(this, arguments); if (sortOrder === 'ascend') { @@ -182,7 +133,7 @@ let AntTable = React.createClass({ sortColumn, sorter }; - this.fetch(newState); + this.setState(newState); this.props.onChange.apply(this, this.prepareParamsArguments(objectAssign({}, this.state, newState))); }, @@ -202,7 +153,7 @@ let AntTable = React.createClass({ selectionDirty: false, filters }; - this.fetch(newState); + this.setState(newState); this.props.onChange.apply(this, this.prepareParamsArguments(objectAssign({}, this.state, newState))); }, @@ -293,7 +244,7 @@ let AntTable = React.createClass({ selectionDirty: false, pagination }; - this.fetch(newState); + this.setState(newState); this.props.onChange.apply(this, this.prepareParamsArguments(objectAssign({}, this.state, newState))); }, @@ -391,10 +342,6 @@ let AntTable = React.createClass({ return columns; }, - getCurrentPageData() { - return this.isLocalDataSource() ? this.getLocalDataPaging() : this.state.data; - }, - getColumnKey(column, index) { return column.key || column.dataIndex || index; }, @@ -458,7 +405,7 @@ let AntTable = React.createClass({ let pagination = objectAssign(this.state.pagination, { pageSize: pageSize }); - this.fetch({pagination}); + this.setState({ pagination }); }, renderPagination() { @@ -470,16 +417,14 @@ let AntTable = React.createClass({ 'ant-table-pagination': true, 'mini': this.props.size === 'middle' || this.props.size === 'small', }); - let total = this.state.pagination.total; - if (!total && this.isLocalDataSource()) { - total = this.getLocalData().length; - } - return (total > 0) ? : null; + let total = this.state.pagination.total || this.getLocalData().length; + return (total > 0) ? + : null; }, prepareParamsArguments(state) { @@ -496,61 +441,13 @@ let AntTable = React.createClass({ return [pagination, filters, sorter]; }, - fetch(newState) { - if (this.isLocalDataSource()) { - if (newState) { - this.setState(newState); - } - } else { - // remote 模式使用 this.dataSource - let dataSource = this.getRemoteDataSource(); - if (!dataSource) { - return null; - } - let state = objectAssign({}, this.state, newState); - if (newState || !this.state.loading) { - this.setState(objectAssign({ - loading: true - }, newState)); - } - let buildInParams = dataSource.getParams.apply(this, this.prepareParamsArguments(state)) || {}; - return reqwest({ - url: dataSource.url, - method: 'get', - data: objectAssign(buildInParams, dataSource.data), - headers: dataSource.headers, - type: 'json', - success: (result) => { - if (this.isMounted()) { - let pagination = objectAssign( - state.pagination, - dataSource.getPagination.call(this, result) - ); - this.setState({ - selectionDirty: false, - loading: false, - data: dataSource.resolve.call(this, result), - pagination: pagination - }); - } - }, - error: () => { - this.setState({ - loading: false, - data: [] - }); - } - }); - } - }, - findColumn(myKey) { return this.props.columns.filter((c) => { return this.getColumnKey(c) === myKey; })[0]; }, - getLocalDataPaging(dataSource) { + getCurrentPageData(dataSource) { let data = this.getLocalData(dataSource); let current, pageSize; let state = this.state; @@ -595,22 +492,14 @@ let AntTable = React.createClass({ if (values.length === 0) { return; } - data = data.filter((record) => { - return values.some((v)=> { - return col.onFilter(v, record); - }); - }); + data = col.onFilter ? data.filter(record => { + return values.some(v => col.onFilter(v, record)); + }) : data; }); } return data; }, - componentDidMount() { - if (!this.isLocalDataSource()) { - this.fetch(); - } - }, - render() { let data = this.getCurrentPageData(); let columns = this.renderRowSelection(); @@ -644,7 +533,7 @@ let AntTable = React.createClass({ expandIconAsCell={expandIconAsCell} /> {emptyText} ; - if (this.state.loading) { + if (this.props.loading) { // if there is no pagination or no data, the height of spin should decrease by half of pagination let paginationPatchClass = (this.hasPagination() && data && data.length !== 0) ? 'ant-table-with-pagination' @@ -661,6 +550,4 @@ let AntTable = React.createClass({ } }); -AntTable.DataSource = DataSource; - export default AntTable; diff --git a/components/table/index.md b/components/table/index.md index 468c7b9d90..b5759ece03 100644 --- a/components/table/index.md +++ b/components/table/index.md @@ -16,14 +16,10 @@ ## 如何使用 -Table 有两种模式,本地数据和远程数据模式。 - -**本地数据模式**是指数据一次性载入内存,纯前端进行分页、筛选、排序等功能。 - -通过指定表格的数据源 `dataSource` 为一个数据数组。 +指定表格的数据源 `dataSource` 为一个数组。 ```jsx -var dataSource = [{ +const dataSource = [{ key: '1', name: '胡彦斌', age: 32, @@ -35,28 +31,22 @@ var dataSource = [{ address: '西湖区湖底公园1号' }]; -
-``` - -**远程数据模式**是更常见的业务场景,是一次只从服务端读取一页的数据放在前端,执行筛选、排序、切换页码等操作时均向后台发送请求,后台返回当页的数据和相关分页信息。 - -> 远程数据模式后续可能删除,目前不推荐使用。 - -通过指定表格的数据源 `dataSource` 为一个 DataSource 的实例如下。 +const columns = [{ + title: '姓名', + dataIndex: 'name' +}, { + title: '年龄', + dataIndex: 'age' +}, { + title: '住址', + dataIndex: 'address' +}]; -```jsx -var dataSource = new Table.DataSource({ - url: '/api/users', - resolve: function(result) { - return result.data; - }, - getPagination: function(result) {}, - getParams: function(pagination, filters, sorter) {} -}); - -
+
``` +> 注:`dataSource` 在 `0.11.0` 版本后不再支持远程模式。 + ## API ### Table @@ -66,7 +56,7 @@ var dataSource = new Table.DataSource({ | rowSelection | 列表项是否可选择 | Object | | false | | pagination | 分页器 | Object | 配置项参考 [pagination](/components/pagination),设为 false 时不显示分页 | | | size | 正常或迷你类型 | String | `default` or `small`| default | -| dataSource | 数据源,可以为数组(本地模式)或一个数据源描述对象(远程模式) | Array or Object | | | +| dataSource | 数据数组 | Array | | | | columns | 表格列的配置描述,具体项见下表 | Array | | 无 | | rowKey | 表格列 key 的取值 | Function(recode, index):string | | record.key | | expandIconAsCell | 设置展开 Icon 是否单独一列 | Boolean | | true | @@ -88,21 +78,10 @@ var dataSource = new Table.DataSource({ | filters | 表头的筛选菜单项 | Array | | | | onFilter | 本地模式下,确定筛选的运行函数 | Function | | | | filterMultiple | 是否多选 | Boolean | | true | -| sorter | 排序函数,本地模式下为一个函数,远程模式下为布尔值 | Function or Boolean | | 无 | +| sorter | 排序函数,本地排序使用一个函数,需要服务端排序可设为 true | Function or Boolean | | 无 | | width | 列宽度 | String or Number | | 无 | | className | 列的 className | String | | 无 | -### dataSource - -远程数据源配置对象。 - -| 参数 | 说明 | 类型 | 可选值 | 默认值 | -|---------------|--------------------------|-----------------|---------------------|---------| -| url | 数据源地址 | String | | | -| resolve | 获得数据的解析函数,接收参数为远程数据返回的 result | Function | | | -| getPagination | 和后台接口返回的分页数据进行适配的函数,返回值会传给表格中的分页器 | Function | | | -| getParams | 和后台接口接收的参数进行适配,返回值会作为请求的参数发送 | Function | | 无 | - ## 注意 按照 React 的[规范](http://facebook.github.io/react/docs/multiple-components.html#dynamic-children),所有的组件数组必须绑定 key。在 Table 中,默认将每列数据的 `key` 属性作为唯一的标识。 diff --git a/package.json b/package.json index d4644bd8fc..4354dcba63 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,6 @@ "rc-upload": "~1.7.0", "rc-util": "~3.0.1", "react-slick": "~0.9.1", - "reqwest": "~2.0.5", "semver": "~5.0.3", "util-deprecate": "~1.0.1", "velocity-animate": "~1.2.2", @@ -106,6 +105,7 @@ "react-dom": "~0.14.2", "react-router": "~1.0.0", "react-stateless-wrapper": "~1.0.2", + "reqwest": "~2.0.5", "webpack": "^1.10.1", "webpack-babel-jest": "^1.0.0", "webpack-dev-middleware": "^1.2.0" diff --git a/scripts/demo.js b/scripts/demo.js index fc03b41014..7c38cc49a0 100644 --- a/scripts/demo.js +++ b/scripts/demo.js @@ -32,6 +32,7 @@ window.React = React; window.ReactDOM = ReactDOM; window['object-assign'] = require('object-assign'); window['classnames'] = require('classnames'); +window['reqwest'] = require('reqwest'); require('./importCss'); antd.Datepicker.locale = { From 58845101c2eaae8b00af06696de9fbbaf55a540f Mon Sep 17 00:00:00 2001 From: afc163 Date: Thu, 10 Dec 2015 15:16:33 +0800 Subject: [PATCH 2/3] update table demos --- components/table/demo/local-data.md | 14 ++++++++++++-- components/table/demo/locale.md | 2 -- components/table/demo/row-selection.md | 2 +- components/table/filterDropdown.jsx | 8 -------- components/table/index.jsx | 4 +--- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/components/table/demo/local-data.md b/components/table/demo/local-data.md index 4a7b5b16a1..3be2649d02 100644 --- a/components/table/demo/local-data.md +++ b/components/table/demo/local-data.md @@ -1,6 +1,7 @@ # 外界控制数据 - order: 11 +- hidden: true 由父元素控制自身数据展示。 @@ -44,7 +45,7 @@ const data2 = [{ age: 32, address: '西湖区湖底公园2号' }, { - key: '22', + key: '2', name: '胡彦祖2', age: 42, address: '西湖区湖底公园2号' @@ -72,8 +73,17 @@ const App = React.createClass({ }); }, render() { + // 通过 rowSelection 对象表明需要行选择 + const rowSelection = { + onSelect: function(record, selected, selectedRows) { + console.log(record, selected, selectedRows); + }, + onSelectAll: function(selected, selectedRows) { + console.log(selected, selectedRows); + } + }; return
-
+
  diff --git a/components/table/demo/locale.md b/components/table/demo/locale.md index d2b1952748..775b11f63a 100644 --- a/components/table/demo/locale.md +++ b/components/table/demo/locale.md @@ -51,8 +51,6 @@ const data = [{ }]; const locale = { - sortAscend: 'Sort ascending', - sortDescend: 'Sort descending', filterTitle: 'Filter', filterConfirm: 'Confirm', filterReset: 'Reset' diff --git a/components/table/demo/row-selection.md b/components/table/demo/row-selection.md index e20827d195..48b698e1fc 100644 --- a/components/table/demo/row-selection.md +++ b/components/table/demo/row-selection.md @@ -2,7 +2,7 @@ - order: 1 -第一列是联动的选择框,rowSelection 中配置 `type="radio"` 可设为单选。 +第一列是联动的选择框。 --- diff --git a/components/table/filterDropdown.jsx b/components/table/filterDropdown.jsx index 550f78e0d8..c656f25ebf 100644 --- a/components/table/filterDropdown.jsx +++ b/components/table/filterDropdown.jsx @@ -71,18 +71,10 @@ let FilterMenu = React.createClass({
{locale.filterConfirm} {locale.filterReset} diff --git a/components/table/index.jsx b/components/table/index.jsx index 93131acff4..ca90def0b1 100644 --- a/components/table/index.jsx +++ b/components/table/index.jsx @@ -23,7 +23,6 @@ let AntTable = React.createClass({ return { // 减少状态 selectedRowKeys: [], - dataSource: this.props.dataSource, filters: {}, selectionDirty: false, sortColumn: '', @@ -92,7 +91,6 @@ let AntTable = React.createClass({ this.setState({ selectionDirty: false, selectedRowKeys, - dataSource: nextProps.dataSource, }); } }, @@ -476,7 +474,7 @@ let AntTable = React.createClass({ getLocalData(dataSource) { let state = this.state; - let data = dataSource || this.state.dataSource; + let data = dataSource || this.props.dataSource; // 排序 if (state.sortOrder && state.sorter) { data = data.sort(state.sorter); From 41c60f6469def118bb6ba23ff60b7fe2e5bfc735 Mon Sep 17 00:00:00 2001 From: afc163 Date: Thu, 10 Dec 2015 15:25:48 +0800 Subject: [PATCH 3/3] Add propTypes --- components/table/index.jsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/components/table/index.jsx b/components/table/index.jsx index ca90def0b1..f8b45557fb 100644 --- a/components/table/index.jsx +++ b/components/table/index.jsx @@ -38,6 +38,7 @@ let AntTable = React.createClass({ getDefaultProps() { return { + dataSource: [], prefixCls: 'ant-table', useFixedHeader: false, rowSelection: null, @@ -52,6 +53,15 @@ let AntTable = React.createClass({ propTypes: { dataSource: React.PropTypes.array, + prefixCls: React.PropTypes.string, + useFixedHeader: React.PropTypes.bool, + rowSelection: React.PropTypes.object, + className: React.PropTypes.string, + size: React.PropTypes.string, + loading: React.PropTypes.bool, + bordered: React.PropTypes.bool, + onChange: React.PropTypes.func, + locale: React.PropTypes.object, }, getDefaultSelection() {