GridManager 库地址:http://gridmanager.lovejavascript.com/index.html
本文旨在说明 GridManager 的使用技巧,如果想了解其配置使用,详见文档说明 https://gridmanager.lovejavascript.com/api/index.html
1. 基础使用—动态数据表格
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| export default class App extends Component { resource = () => fetch( "https://www.lovejavascript.com/learnLinkManager/getLearnLinkList" ).then((res) => res.json());
columnData = [ { key: "name", text: "名称", align: "left" }, { key: "info", text: "使用说明" } ];
render() { return ( <div className="App"> <Table gridManagerName="test" disableLine supportAjaxPage checkboxConfig={{ useRowCheck: true }} supportDrag={false} supportCheckbox={false} ajaxData={this.resource} columnData={this.columnData} /> </div> ); }
|
完整代码演示:https://codesandbox.io/s/optimistic-currying-1bxpj?file=/src/App.js
2. 静态数据表格(分页、排序、搜索、下载)
使用场景:需要纯前端处理表格数据,这时候,我们往往需要在前端实现分页、排序、搜索和下载等函数的封装。
因为每次刷新表格的时候,都会调用 ajaxData 方法,这个方法会返回表格数据,因此,我们只需要在 ajaxData 方法中调用上述封装好的函数即可达到我们要的效果。
这种写法很像过滤器,每一个方法都是对原数据的一次过滤,最后返回过滤后的数据,下面是每个方法的实现:
原始数据originData
—filter—> searchData(originData): searchedData
—filter—> sortingData(searchedData): sortedData
—filter—> paging(sortedData): pagedData
——>处理后的数据
ajaxData 配置:
1 2 3 4 5 6 7 8 9 10 11
| ajaxData = async (settting, params) => { const originData = this.store.fetchData(); const searchedData = this.store.searchData(originData, this.state.keywords); const sortedData = this.store.sortingData(searchedData, params); this.csvData = sortedData.list; return await this.store.pagingData( sortedData, params.pageNum, params.pageSize ); };
|
分页:
1 2 3 4 5 6 7 8 9
| pagingData(data, pageNum, pageSize) { const { list } = data; return Promise.resolve({ pageNum, pageSize, totals: list.length, list: list.slice((pageNum - 1) * pageSize, pageNum * pageSize) }); }
|
排序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| sortingData(data, query) { let sortProps = "DESC"; let sortOrder = ""; Object.keys(query).forEach((key) => { if (query[key] === "ASC" || query[key] === "DESC") { sortProps = key.split("_")[1]; sortOrder = query[key]; } }); const list = this.sort(data.list, sortProps, sortOrder); return { totals: list.length, list }; } sort(list, sortProps, sortOrder) { if (sortOrder === "ASC") { return sortBy(list, sortProps); } if (sortOrder === "DESC") { return sortBy(list, sortProps).reverse(); } return list; }
|
搜索关键字:
1 2 3 4 5 6 7 8 9
| searchData(data, keywords) { const list = data.list.filter( (item) => item.name && item.name.indexOf(keywords) > -1 ); return { totals: list.length, list }; }
|
下载:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| download(list, fileName) { if (!fileName) return;
const url = window.URL.createObjectURL( new window.Blob([`\ufeff${list.join("\r\n")}`]) ); const link = document.createElement("a"); const evt = document.createEvent("MouseEvents");
link.href = url; link.setAttribute("download", fileName);
evt.initEvent("click");
link.dispatchEvent(evt); }
|
完整代码演示: https://codesandbox.io/s/beautiful-faraday-jt3i3?file=/src/App.js
3. 多选表格(数据回显、设置行选中的唯一key值、禁用行选中、最大选中行的限制)
表格选中数据回显
1 2 3 4 5 6 7 8 9 10 11
| getCheckedData() { return Table.getCheckedData(this.gridManagerName); }
setCheckedData(checkedData) { Table.setCheckedData(this.gridManagerName, checkedData); }
ajaxSuccess() { this.setCheckedData(this.state.selected); }
|
设置行选中的唯一key值:
表格方法 getCheckedData 返回的是完整的已选数据,表格回显的前提是传入的数据和传出的数据格式一样,这在使用中会造成局限,比如说后端并不会存储完整的数据,而是只存储每条数据的 id,这是很常见的场景,因此在 GridManager 后面的迭代中,在 checkboxConfig 中添加了 key 属性,只需要配置 key: ‘id’,在传入的已选数据中,每条数据只需要包括 id 即可,不需要完整的数据结构也可以完成回显。
1 2 3
| <Table checkboxConfig: { useRowCheck: true, key: 'id' }, />
|
禁用行选中
1 2 3 4 5 6 7
| onGridRowRender(row) { const disabledId = [69, 68]; if (disabledId.indexOf(row.id) > -1) { Object.assign(row, { gm_checkbox_disabled: true }); } return row; }
|
最大选中行限制:
需要调用 checkedGridBefore 和 checkedGridAllBefore 这两个方法来完成此需求,由于触发 checkedAllBefore 之后也会触发 checkedBefore,因此这里需要特殊处理一下,防止出现两次 error 提示,详细见下面的代码实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| checkedGridBefore = (checkedList, isChecked) => { if (checkedList.length >= MAX_NUM && !isChecked) { Message.error("最多支持同时选择5个"); return false; } return true; };
checkedGridAllBefore(checkedList, isChecked) { const unChecked = this.dataList .map((item) => !checkedList.find((item1) => item.id === item1.id)) .filter(Boolean);
if (unChecked.length + checkedList.length > MAX_NUM && !isChecked) { // 触发 checkedAllBefore 之后也会触发 checkedBefore,这里需要特殊处理一下,防止出现两次 error 提示 if (checkedList.length < MAX_NUM) { Message.error("最多支持同时选择5个"); } return false; } return true; }
|
完整代码演示:https://codesandbox.io/s/dazzling-albattani-o7dtn?file=/src/App.js
4. 树状表格
在表格基本配置的基础上,添加 supportTreeData = true 以及 treeConfig 即可完成一个树表格的展示。
1 2 3 4
| ... supportTreeData treeConfig={{ treeKey: "children" }} ...
|
完整代码演示:https://codesandbox.io/s/shy-smoke-7ltz2?file=/src/App.js
5. 常用的一些使用优化(firstLoading, isIconFollowText,拖拽、隐藏列)
firstLoading:
设置 firstLoading = false,可以让表格先渲染出来,然后再加载数据。
使用场景:表格数据的请求返回较慢,这时,设置 firstLoading = false,表格就会先渲染,交互上会更加友好。
注意事项:需要配合 callback 函数使用,在 callback 函数中调用刷新表格的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| reloadGrid(gotoPage) { Table.setQuery(this.gridManagerName, this.queryParams, gotoPage); }
gridInit = () => { this.reloadGrid(1); };
render() { return ( <div className="App"> <Table gridManagerName={this.gridManagerName} disableLine supportAjaxPage ajaxData={this.ajaxData} columnData={this.columnData} supportCheckbox={false} firstLoading={false} callback={this.gridInit} /> </div> ); }
|
完整代码演示:https://codesandbox.io/s/quirky-https-k06m9?file=/src/App.js
isIconFollowText:
可以设置表头的icon图标是否跟随文本,默认图标是在左侧,设置后会跟在文本右侧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| columnData = [ { key: "name", text: "名称", align: "left", sorting: "", // 表头 tooltip 配置 remind: { text: "字段说明字段说明字段说明字段说明字段说明字段说明", style: { "text-align": "left" } } } ];
render() { return ( <div className="App"> <Table gridManagerName={this.gridManagerName} disableLine supportAjaxPage ajaxData={this.ajaxData} columnData={this.columnData} supportCheckbox={false} isIconFollowText /> </div> ); }
|
完整代码演示:https://codesandbox.io/s/interesting-dust-wwe85?file=/src/App.js:574-1194
拖拽:
在拖拽的场景中,如果涉及到表格的新增和删除,不要直接对 ajaxData 进行操作,操作原数据,ajaxData 由原数据包装而来,从而保证单一职责(详细栗子请看完整代码)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| ajaxData = async (settting, params) => { return Promise.resolve({ data: this.state.dataList, // dataList:原数据 totals: this.state.dataList.length }); };
onAdd() { const { dataList } = this.state; // dataList:原数据 dataList.push({ id: new Date().getTime(), name: "浏览器的工作原理" }); this.setState({ dataList }); this.reloadGrid(); }
render() { const moveRowConfig = { key: "priority", handler: (list, tableData) => { console.log(tableData); }, useSingleMode: true // 第一列显示拖拽图标 };
return ( <div className="App"> <Button onClick={() => this.onAdd()}>新增</Button> <Table gridManagerName={this.gridManagerName} disableLine supportAjaxPage={false} ajaxData={this.ajaxData} columnData={this.columnData} supportCheckbox={false} supportMoveRow moveRowConfig={moveRowConfig} /> </div> ); }
|
完整代码演示:https://codesandbox.io/s/jovial-water-8y4if?file=/src/App.js
隐藏列
使用场景:需要展示的列比较多或者有隐藏列的需求。
使用:在 columnData 数组新增一项配置即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| { key: "operate", disableCustomize: true, text: ( <Icon type="config" style={{ cursor: "pointer", fontWeight: "bold" }} onClick={() => this.onSetUpGridFiled()} /> ), template: () => "", width: "30px" } onSetUpGridFiled() { Table.setConfigVisible(this.gridManagerName, true); }
|
完整代码演示:https://codesandbox.io/s/sharp-perlman-1elht?file=/src/App.js:1094-1174