网站开发中,仅仅是简单展示一下数据还远远不够,我们还会需要对数据进行更新的操作。

本小节中,我们会在页面中添加一个按钮。点击后弹出对话框,允许用户输入一条新的数据并进行更新。

引入相关依赖

我们将本次需要的组件引入进来。

  1. import { Table, Modal, Button, Form, Input } from 'antd';
  2. const FormItem = Form.Item;

对话框

我们在页面中插入新建按钮和对话框组件。

  1. <div>
  2. <Table ... />
  3. <Button>新建</Button>
  4. <Modal title="新建记录">
  5. ...
  6. </Modal>
  7. </div>

其中,对于 Modal 组件,我们可以通过 visible 属性来控制是否显示。

因此,我们需要将其在 state 中进行管理。

  1. class List extends React.Component {
  2. state = {
  3. visible: false,
  4. };
  5. // ...
  6. }

按钮事件

让我们为按钮添加相应事件,使其可以改变 state 中 visible 的值。

  1. class List extends React.Component {
  2. showModal = () => {
  3. this.setState({ visible: true });
  4. };
  5. // ...
  6. }
  1. <Button onClick={this.showModal}>新建</Button>

设置好后,我们页面中点击按钮便会弹出对话框了。

表单

antd 提供了一套非常强大的表单组件,大部分情况下只需要简单的几步配置便可以实现验证功能。首先,我们需要将页面与表单进行关联:

  1. export default connect(mapStateToProps)(Form.create()(List));

其中,最主要的代码是:

  1. Form.create()(List)

这段代码的作用是创建一个高阶组件,为页面组件 List 提供表单所需要的内容(this.props.form)。

现在,我们来让对话框关联 visible 并且添加上表单支持:

  1. render() {
  2. const { visible } = this.state;
  3. const { form: { getFieldDecorator } } = this.props;
  4. // ...
  5. return (
  6. <div>
  7. {/* ... */}
  8. <Modal
  9. title="新建记录"
  10. visible={visible}
  11. >
  12. <Form>
  13. <FormItem label="名称">
  14. {getFieldDecorator('name', {
  15. rules: [{ required: true }],
  16. })(
  17. <Input />
  18. )}
  19. </FormItem>
  20. <FormItem label="描述">
  21. {getFieldDecorator('desc')(
  22. <Input />
  23. )}
  24. </FormItem>
  25. <FormItem label="链接">
  26. {getFieldDecorator('url', {
  27. rules: [{ type: 'url' }],
  28. })(
  29. <Input />
  30. )}
  31. </FormItem>
  32. </Form>
  33. </Modal>
  34. </div>
  35. );
  36. }
  37. }

我们可以看到表单组件是通过 Form 与 Form.Item (我们之前定义了 FormItem = Form.item) 配合使用,其中每一个 Form.Item 都是一个表单域。而 getFieldDecorator 是用于将包裹的组件与表单进行双向绑定使用。

此外,我们还可以设置改表单域是否是必填项(required: true)或者是否需要类型检查(type: url)。更多的配置可以查询官方文档

然后,我们添加表单处理逻辑。添加确认和取消方法。

撤销操作

重置 visible 属性为 false 以关闭对话框。

  1. handleCancel = () => {
  2. this.setState({
  3. visible: false,
  4. });
  5. }

确定操作

我们通过 validateFields 方法验证表单是否完成填写,通过便提交添加操作。

  1. handleOk = () => {
  2. const { dispatch, form: { validateFields } } = this.props;
  3. validateFields((err, values) => {
  4. if (!err) {
  5. dispatch({
  6. type: 'cards/addOne',
  7. payload: values,
  8. });
  9. // 重置 `visible` 属性为 false 以关闭对话框
  10. this.setState({ visible: false });
  11. }
  12. });
  13. }

其中, dispatch 的 'cards/addOne' 请参考我们提供的对应样例中 src/model/cardssrc/service/cardsmock/cards 的代码。该内容已经在第三章中讲解因而不再重复。

最后,我们为 Modal 添加事件处理:

  1. <Modal
  2. title="新建记录"
  3. visible={visible}
  4. onOk={this.handleOk}
  5. onCancel={this.handleCancel}
  6. >
  7. ...
  8. </Modal>

自定义控件

在 antd 中,我们提供了诸如 Input, Select 之类的用于接收用户输入的组件。但是如果这些不满足你的需要时该怎么办呢?比如你如果需要一个富文本输入框,又或者是一个复杂的多行内容输入的表格。我们怎么可以添加这些复杂的组件,让它们可以和 antd 的 Form 组件一起使用呢?

其实很简单,在上面我们介绍了 getFieldDecorator 这个方法,它执行后会返回一个函数,那个函数接收一个参数,那个参数就是一个输入组件。比如在上面的例子中它可能是 <Input /> 也有可能是 <Select />。但是它并没有被局限在 antd 支持的组件内,你完全可以传入你自己的一个组件,比如下面的示例:

  1. <FormItem label="自定义输入">
  2. {getFieldDecorator('custom', {
  3. rules: [{ required: true }],
  4. })(
  5. <YourInput />
  6. )}
  7. </FormItem>

其中,只要 YourInput 这个组件满足如下三个条件即可:

  • 提供受控属性 value 或其它与 valuePropName 的值同名的属性。
  • 提供 onChange 事件或 trigger 的值同名的事件。
  • 不能是函数式组件。

具体的可运行的例子你可以参考 Ant Design 官网的例子

所以,如果你需要在表单中添加一个富文本组件,那么你可以在 Ant Design 官网推荐的社区精选组件中找到合适你项目的富文本编辑器组件。然后你可以自定义一个组件,该组件应该封装你找到的编辑器子组件并满足上面说的三个条件,这样你就可以在你的表单中使用它了。

思考

洋洋洒洒我们写了这么多的代码,是时候思考一下其他问题了。

目前的代码能够实现功能,但是这是最好的实现吗?
函数名和变量是否可以再改改?
是否可以把一部分代码抽离出来做成独立的模块呢?
现在页面样式布局是否还能再进行一些调整呢?
等等……

这就交给各位独立思考啦。