手写实现 rc-field-form (二)

9,510 阅读3分钟

「这是我参与2022首次更文挑战的第36天,活动详情查看:2022首次更文挑战」。

写在前面

  • 前面一篇文章已经简单说了一下,rc-form 到 rc-field-form 的改变,并且展示了 rc-field-form 的使用
  • 今天这篇文章我们来一步一步实现完善我们自己的 rc-field-form

实现 Input 组件

  • 下面我们简单封装一个 Input 组件,用作我们业务开发中的数据输入组件
export function Input(props) {
  const { value = "", ...otherProps } = props;
  return <input style={{ outline: "none" }} value={value} {...otherProps} />;
}
  • 为啥不直接使用 input 框呢
  • 其实跟我们的使用方法有关系
<Field name="user" label="账号" rules={userRules}>
    <Input placeholder="请输入账号" />
</Field>
  • 因为这里如果直接使用 input,就需要给它设置一个 value,但是我们前面也说了,所有的数据输入组件的 value 都要被统一管理起来
  • 而这个数据托管的操作是在 Field 组件中做的,在使用 Input 组件时,是拿不到 value 的
  • 所以在这里做了一层封装,从 props 中取出 value 值,默认为空字符串 "",避免不传 value,导致数据输入时,出现非受控组件的报错

image.png

  • 最后数据输入时,在 Field 组件内部,会将托管的 value 值传给 Input 组件,而 Input 组件的 props 中的 value 值也会变成真实输入的数据

创建数据仓库

  • 我们需要创建一个 store 用来统一托管存储,用户输入的数据,然后让所有组件直接从 store 中获取数据,这样某个数据输入组件的数据发生改变,也只用更新自己即可,不会引起其他同级的数据输入组件进行更新,从而最大程度避免性能浪费
  • 下面创建一个 FormStore,专门用于管理 Form 组件的所有数据
class FormStore {
  constructor() {
    this.store = {}; // 用于存放组件数据
  }

  // 实现操作状态的方法 get set
 
 // 多个字段的 set 操作
  setFieldsValue = (newStore) => {
    this.store = {
      ...this.store,
      ...newStore,
    };
  };

  // 多个字段的 get 操作
  getFieldsValue = () => ({ ...this.store });

  // 单个字段的 set 操作
  setFieldValue = (field, val) => {
    this.setFieldsValue({ [field]: val });
  };

  // 单个字段的 get 操作
  getFieldValue = (fieldName) => this.store[fieldName];

  // 暴露操作状态的方法
  getForm = () => ({
    getFieldsValue: this.getFieldsValue,
    setFieldsValue: this.setFieldsValue,
    setFieldValue: this.setFieldValue,
    getFieldValue: this.getFieldValue,
  });
}
  • 在上面的 FormStore 中,使用 store 用来存放数据
  • 实现了四个方法,其中 setFieldsValue 与 getFieldsValue 是用于多字段的数据存与取,setFieldValue 与 getFieldValue 是用于单字段的数据存与取
  • 最后实现了一个 getForm 方法,用于暴露数据仓库 store 的相关操作方法

小结

  • 这篇文章,我们在组件之外,创建了一个数据仓库,用于集中管理 Form 组件的所有数据
  • 这个数据仓库独立与 Form,那它们之间如何进行交互呢?如何在更新数据后,就让相应的组件产生更新?
  • 下篇文章我们就会解决这个问题

最后

  • 今天的分享就到这里了,欢迎大家在评论区里面进行讨论 👏。
  • 如果觉得文章写的不错的话,希望大家不要吝惜点赞,大家的鼓励是我分享的最大动力 🥰