## 按钮加载逻辑
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. 看到这里,相信大家对封装对列表组件应该有个大致的认识了,下面我们来看一下如果进行自定义按钮的配置。