## 按鈕加載邏輯
1. 整個列表頁只有一個Grid組件,卻動態加載出了按鈕,我們不妨看一看這個組件是如何實現的
2. 點進Grid組件,拉到最底下查看render返回,發現封裝了3個子組件
~~~
<Card bordered={false} {...cardProps}>
<div className={styles.swordPage}>
<SearchBox onSubmit={this.handleSearch} onReset={this.handleFormReset}>
{renderSearchForm(this.handleFormReset)}
</SearchBox>
<ToolBar
buttons={buttons}
renderLeftButton={renderLeftButton}
renderRightButton={renderRightButton}
onClick={this.handelToolBarClick}
/>
<StandardTable
rowKey={rowKey || 'id'}
selectedRows={selectedRows}
loading={loading}
columns={columns}
data={data}
onSelectRow={this.handleSelectRows}
onChange={this.handleStandardTableChange}
scroll={scroll}
tblProps={tblProps}
size="middle"
/>
</div>
</Card>
~~~
3. 這3個組件分別為 `SearchBox` 、`ToolBar`、 `StandardTable` ,我們主要來看`ToolBar`
4. `ToolBar`傳入了4個參數:`buttons` 、`renderLeftButton` 、`renderRightButton`、`onClick`
5. buttons就是根據列表頁傳入的菜單code,通過執行getButton方法從而獲取到的按鈕集合
~~~
export default class Grid extends PureComponent {
constructor(props) {
super(props);
this.state = {
current: 1,
size: 10,
formValues: {},
selectedRows: [],
buttons: getButton(props.code),
};
}
}
~~~
6. 進入ToolBar查看源碼,發現其實很簡單,就是根據buttons數據集合動態生成了按鈕。當中有一點需要注意的是 `buttons.filter(button => button.action === 1 || button.action === 3)`,他根據action字段來判斷,這個action代表按鈕類型:1:只有工具欄才出現;2:只有表格行才出現;3:兩者都出現。
~~~
export default class ToolBar extends PureComponent {
render() {
const { buttons, renderLeftButton, renderRightButton, onClick } = this.props;
return (
<div className={styles.operator}>
<div>
{buttons
.filter(button => button.action === 1 || button.action === 3)
.map(button => (
<Button
key={button.code}
icon={button.source}
type={
button.alias === 'delete'
? 'danger'
: button.alias === 'add'
? 'primary'
: 'default'
}
onClick={() => {
onClick(button);
}}
>
<FormattedMessage id={`button.${button.alias}.name`} />
</Button>
))}
{renderLeftButton ? renderLeftButton() : null}
{renderRightButton ? (
<div style={{ float: 'right', marginRight: '20px' }}>{renderRightButton()}</div>
) : null}
</div>
</div>
);
}
}
~~~
7. 其中都 `renderLeftButton` 、`renderRightButton`則是提供大家這列表頁自定義的按鈕,傳入組件,從而生成,不受限于通過菜單接口返回的數據
8. `onClick` 則是組件定義的一些默認點擊事件,大家也可以自行拓展,下面是封裝的方法。可以看到方法根據菜單中定義的 `按鈕別名` 來判斷執行不同的操作。若一個code為 notice_add ,一個code為 news_add,兩個按鈕的別名同為 add,則這兩個按鈕點擊后都會進入第一個判斷并執行。若后續有通用的按鈕事件,大家也可以在這里自定義拓展。
~~~
handelClick = (btn, keys = []) => {
const { path, alias } = btn;
const { btnCallBack } = this.props;
const refresh = (temp = true) => this.refreshTable(temp);
if (alias === 'add') {
if (keys.length > 1) {
message.warn('父記錄只能選擇一條!');
return;
}
if (keys.length === 1) {
router.push(`${path}/${keys[0]}`);
return;
}
router.push(path);
return;
}
if (alias === 'edit') {
if (keys.length <= 0) {
message.warn('請先選擇一條數據!');
return;
}
if (keys.length > 1) {
message.warn('只能選擇一條數據!');
return;
}
router.push(`${path}/${keys[0]}`);
return;
}
if (alias === 'view') {
if (keys.length <= 0) {
message.warn('請先選擇一條數據!');
return;
}
if (keys.length > 1) {
message.warn('只能選擇一條數據!');
return;
}
router.push(`${path}/${keys[0]}`);
return;
}
if (alias === 'delete') {
if (keys.length <= 0) {
message.warn('請先選擇要刪除的記錄!');
return;
}
Modal.confirm({
title: '刪除確認',
content: '確定刪除選中記錄?',
okText: '確定',
okType: 'danger',
cancelText: '取消',
async onOk() {
const response = await requestApi(path, { ids: keys.join(',') });
if (response.success) {
message.success(response.msg);
refresh();
} else {
message.error(response.msg || '刪除失敗');
}
},
onCancel() {},
});
return;
}
if (btnCallBack) {
btnCallBack({ btn, keys, refresh });
}
};
~~~
9. 看到這里,相信大家對封裝對列表組件應該有個大致的認識了,下面我們來看一下如果進行自定義按鈕的配置。