网站开发中,仅仅是简单展示一下数据还远远不够,我们还会需要对数据进行更新的操作。
本小节中,我们会在页面中添加一个按钮。点击后弹出对话框,允许用户输入一条新的数据并进行更新。
引入相关依赖
我们将本次需要的组件引入进来。
import { Table, Modal, Button, Form, Input } from 'antd';
const FormItem = Form.Item;
对话框
我们在页面中插入新建按钮和对话框组件。
<div>
<Table ... />
<Button>新建</Button>
<Modal title="新建记录">
...
</Modal>
</div>
其中,对于 Modal 组件,我们可以通过 visible
属性来控制是否显示。
因此,我们需要将其在 state 中进行管理。
class List extends React.Component {
state = {
visible: false,
};
// ...
}
按钮事件
让我们为按钮添加相应事件,使其可以改变 state 中 visible
的值。
class List extends React.Component {
showModal = () => {
this.setState({ visible: true });
};
// ...
}
<Button onClick={this.showModal}>新建</Button>
设置好后,我们页面中点击按钮便会弹出对话框了。
表单
antd 提供了一套非常强大的表单组件,大部分情况下只需要简单的几步配置便可以实现验证功能。首先,我们需要将页面与表单进行关联:
export default connect(mapStateToProps)(Form.create()(List));
其中,最主要的代码是:
Form.create()(List)
这段代码的作用是创建一个高阶组件,为页面组件 List
提供表单所需要的内容(this.props.form
)。
现在,我们来让对话框关联 visible
并且添加上表单支持:
render() {
const { visible } = this.state;
const { form: { getFieldDecorator } } = this.props;
// ...
return (
<div>
{/* ... */}
<Modal
title="新建记录"
visible={visible}
>
<Form>
<FormItem label="名称">
{getFieldDecorator('name', {
rules: [{ required: true }],
})(
<Input />
)}
</FormItem>
<FormItem label="描述">
{getFieldDecorator('desc')(
<Input />
)}
</FormItem>
<FormItem label="链接">
{getFieldDecorator('url', {
rules: [{ type: 'url' }],
})(
<Input />
)}
</FormItem>
</Form>
</Modal>
</div>
);
}
}
我们可以看到表单组件是通过 Form 与 Form.Item (我们之前定义了 FormItem = Form.item
) 配合使用,其中每一个 Form.Item 都是一个表单域。而 getFieldDecorator
是用于将包裹的组件与表单进行双向绑定使用。
此外,我们还可以设置改表单域是否是必填项(required: true
)或者是否需要类型检查(type: url
)。更多的配置可以查询官方文档。
然后,我们添加表单处理逻辑。添加确认和取消方法。
撤销操作
重置 visible
属性为 false 以关闭对话框。
handleCancel = () => {
this.setState({
visible: false,
});
}
确定操作
我们通过 validateFields
方法验证表单是否完成填写,通过便提交添加操作。
handleOk = () => {
const { dispatch, form: { validateFields } } = this.props;
validateFields((err, values) => {
if (!err) {
dispatch({
type: 'cards/addOne',
payload: values,
});
// 重置 `visible` 属性为 false 以关闭对话框
this.setState({ visible: false });
}
});
}
其中, dispatch 的 'cards/addOne'
请参考我们提供的对应样例中 src/model/cards
、 src/service/cards
和 mock/cards
的代码。该内容已经在第三章中讲解因而不再重复。
最后,我们为 Modal 添加事件处理:
<Modal
title="新建记录"
visible={visible}
onOk={this.handleOk}
onCancel={this.handleCancel}
>
...
</Modal>
自定义控件
在 antd 中,我们提供了诸如 Input, Select 之类的用于接收用户输入的组件。但是如果这些不满足你的需要时该怎么办呢?比如你如果需要一个富文本输入框,又或者是一个复杂的多行内容输入的表格。我们怎么可以添加这些复杂的组件,让它们可以和 antd 的 Form 组件一起使用呢?
其实很简单,在上面我们介绍了 getFieldDecorator
这个方法,它执行后会返回一个函数,那个函数接收一个参数,那个参数就是一个输入组件。比如在上面的例子中它可能是 <Input />
也有可能是 <Select />
。但是它并没有被局限在 antd 支持的组件内,你完全可以传入你自己的一个组件,比如下面的示例:
<FormItem label="自定义输入">
{getFieldDecorator('custom', {
rules: [{ required: true }],
})(
<YourInput />
)}
</FormItem>
其中,只要 YourInput
这个组件满足如下三个条件即可:
- 提供受控属性
value
或其它与valuePropName
的值同名的属性。 - 提供
onChange
事件或trigger
的值同名的事件。 - 不能是函数式组件。
具体的可运行的例子你可以参考 Ant Design 官网的例子。
所以,如果你需要在表单中添加一个富文本组件,那么你可以在 Ant Design 官网推荐的社区精选组件中找到合适你项目的富文本编辑器组件。然后你可以自定义一个组件,该组件应该封装你找到的编辑器子组件并满足上面说的三个条件,这样你就可以在你的表单中使用它了。
思考
洋洋洒洒我们写了这么多的代码,是时候思考一下其他问题了。
目前的代码能够实现功能,但是这是最好的实现吗?
函数名和变量是否可以再改改?
是否可以把一部分代码抽离出来做成独立的模块呢?
现在页面样式布局是否还能再进行一些调整呢?
等等……
这就交给各位独立思考啦。