01. formik介绍及安装

简介

  • formik是一个React库,用于构建强壮且易于了解的表单处理逻辑。
  • 它削减了表单的样板代码量,并帮助处理表单的状况、校验和过错处理。

安装

  • 运用npm安装formik:npm install formik --save
  • 如运用yarn:yarn add formik

简单运用

import { useFormik } from 'formik';
function App() {
    const formik = useFormik({
        initialValues: { username: '张三' },
        onSubmit: values => { }
    });
    return (
        <form onSubmit={formik.handleSubmit}>
            <input type="text" name="username"
                value={formik.values.username}
                onChange={formik.handleChange}
            />
            <input type="submit" />
        </form>
    );
}

formik和antd表单组件联合运用

import React from 'react';
import { Formik } from 'formik';
import { Form, Input, Button, message } from 'antd';
const LoginForm = () => {
  return (
    <Formik
      initialValues={{ username: '', password: '' }}
      onSubmit={(values, actions) => {
        message.success(`登录成功:用户名 - ${values.username},暗码 - ${values.password}`);
        actions.setSubmitting(false);
      }}
    >
      {({ values, handleChange, handleBlur, handleSubmit, isSubmitting }) => (
        <Form onFinish={handleSubmit}>
          <Form.Item label="用户名">
            <Input
              name="username"
              onChange={handleChange}
              onBlur={handleBlur}
              value={values.username}
            />
          </Form.Item>
          <Form.Item label="暗码">
            <Input.Password
              name="password"
              onChange={handleChange}
              onBlur={handleBlur}
              value={values.password}
            />
          </Form.Item>
          <Form.Item>
            <Button type="primary" htmlType="submit" disabled={isSubmitting}>
              登录
            </Button>
          </Form.Item>
        </Form>
      )}
    </Formik>
  );
};
export default LoginForm;

02. formik基础解说(一)

基本准则

  • formik选用React理念简化表单处理,它供给了<Formik />组件封装表单的状况和行为。
  • 支撑受控组件和非受控组件。

运用formik

  • 运用<Formik />组件能够容易地创立一个表单,并经过其valueshandleSubmit特点办理表单状况和提交。

03. formik基础解说(二)

表单字段

  • 经过<Field />组件来办理各个表单字段,如<Field type="text" name="firstName" />
  • formik自动衔接<Field />到表单状况,无需手动办理onChange和value特点。

表单校验

  • formik能够在字段和表单级别进行校验,能够同步或异步返回过错目标。
  • 必须设置validate或validationSchema特点来奉告formik怎么进行校验。

下面是一个验证的示例:

import React from 'react';
import { useFormik } from 'formik';
function App() {
  const formik = useFormik({
    initialValues: { 
      username: '', 
      password: '' 
    },
    validate: values => {
      const errors = {};
      if (!values.username) {
        errors.username = '请输入用户名';
      } else if (values.username.length > 15) {
        errors.username = '用户名的长度不能超过15';
      }
      if (values.password.length < 6) {
        errors.password = '暗码的长度不能小于6';
      }
      return errors;
    },
    onSubmit: values => {
      console.log(values);
    },
  });
  return (
    <form onSubmit={formik.handleSubmit}>
      <input
        type="text"
        name="username"
        value={formik.values.username}
        onChange={formik.handleChange}
        onBlur={formik.handleBlur}
      />
      {formik.touched.username && formik.errors.username ? (
        <div>{formik.errors.username}</div>
      ) : null}
      <input
        type="password"
        name="password"
        value={formik.values.password}
        onChange={formik.handleChange}
        onBlur={formik.handleBlur}
      />
      {formik.touched.password && formik.errors.password ? (
        <div>{formik.errors.password}</div>
      ) : null}
      <button type="submit">提交</button>
    </form>
  );
}
export default App;

表单校验的机遇需求被指定为适宜的机遇,这样能够提高用户运用的体验感。下面就经过onBlur事情对其进行改善。

这里能够利用formik.touched这个目标,比如用户现已修改正username的值,那么formik.touched.username的值就不再为假了。

onBlur={formik.handleBlur}
onBlur={formik.handleBlur}
<p>{formik.touched.username && formik.errors.username ? formik.errors.username : null}</p>
<p>{formik.touched.password && formik.errors.password ? formik.errors.password : null}</p>

上述的代码进行了两个方面的改善:1. 在表单失掉焦点之后才进行校验; 2. 假如一个表单的内容从来没有被更改正,则不会对其进行校验。

04. formik结合yup进行表单验证

yup介绍

  • yup是一个构建目标形式的JavaScript形式验证器,用于验证和解析数据。
  • 它供给了一种声明式办法来创立校验形式。

验证办法

  • formik结合yup能够轻松完成表单验证:validationSchema={Yup.object({...})}
  • yup答应创立杂乱的校验逻辑,如必填项、字符长度、正则表达式等。

运用yup能够有效削减表单验证过程中的代码量,并且使代码逻辑变得简练。这得益于其对常见的表单验证规则的高度封装,在运用的时分咱们只需求查询然后运用适宜的规则即可。
首要安装yup: yarn add yup

  import * as Yup from "yup";
  ...
  const schema = Yup.object({
    username: Yup.string()
      .max(15, "用户名的长度不能大于15")
      .required("请输入用户名"),
    password: Yup.string().min(6, '暗码长度不能少于6位'),
  });
  validationSchema={schema}

运用validationSchema和yup搭配之后就不需求再运用validate配置了。

05. 运用getFieldProps办法简化代码

简化表单代码

  • getFieldProps是formik供给的一个实用办法,它封装了字段的value, onChange和onBlur事情。
  • 适用于快速完成常见的表单字段,能够明显削减重复代码量。

也就是说,形如下的代码能够被简化:

      <input
        type="password"
        name="password"
        value={formik.values.password}
        onChange={formik.handleChange}
        onBlur={formik.handleBlur}
      />

简化之后的代码为:

      <input
        type="password"
        name="password"
        {...formik.getFieldProps('password')}
      />

当然,假如你想要自界说onChange或者onBlur的回调,上述的做法明显就不适宜了。

06. 运用组件的方式构建表单

组件化表单

  • formik支撑构建和复用表单组件,经过<Formik />组件和Context API完成跨组件通信。
  • 能够创立包装<Field />的自界说组件,提高代码复用性和可维护性。

React组件

  • formik完全遵守React的组件化准则,能够和其他库或自界说逻辑无缝集成。
// 引入React核心库
import React from "react"; 
// 引入Formik库相关的组件,Formik是用于构建表单的React库
import { Formik, Form, Field, ErrorMessage } from "formik"; 
// 引入Yup库,Yup是用于构建目标形式的JavaScript schema builder,可用于值的校验
import * as Yup from "yup";
// 界说App函数组件
function App() {
  // 设置表单的初始值
  const initialValues = {username: '', hobbies: ['足球', '篮球']};
  // 提交表单触发的函数,这里仅仅将表单的值打印在控制台
  const handleSubmit = (values) => {
    console.log(values);
  };
  // 运用Yup界说校验形式
  const schema = Yup.object({
    // 界说username字段为字符串类型,最大长度为15,并且是必填项
    username: Yup.string()
      .max(15, "用户名的长度不能大于15")
      .required("请输入用户名"),
  });
  // 烘托组件
  return (
    // Formik组件用来包裹整个表单,并供给表单办理的功能
    <Formik
      initialValues={initialValues} // 设置初始化值
      onSubmit={handleSubmit} // 提交表单履行的函数
      validationSchema={schema} // 设置表单校验的形式
    >
      {/* Form组件表示一个表单 */}
      <Form>
        {/* Field组件,对应一个input输入框,name特点指明它是formik办理 state中的哪一个字段  */}
        <Field name="username" />
        {/* ErrorMessage 组件用于显现与Field组件同名字段的过错信息 */}
        <ErrorMessage name="username" />
        {/* 提交按钮 */}
        <input type="submit"/>
      </Form>
    </Formik>
  );
}
// 将App组件导出,答应在其他文件中运用
export default App;

虽然运用组件的方式结构表单很方便,但是相应的自在度上收到了比较大的限制。

07. field组件的as特点

默认情况下,Field组件烘托的是文本框,假如想要生成其他表单元素能够选用as特点:

<Field name="content" as="textarea" />
<Field name="subject" as="select">
  <option value="前端">前端</option>
  <option value="Java">Java</option>
  <option value="python">python</option>
</Field>

08. 自界说表单控件

明显Field组件即使选用了as特点作为其拓宽的重要方式,但是仍是会有很多不如意的当地,这个时分让开发者自行封装符合自己项目主题的表单控件就显得尤为重要了!

下面,就经过useField钩子函数封装一个表单控件。

import { useField } from "formik";
function MyIpt ({label, ...props}) {
    const [field, meta] = useField(props);
    return (
        <div>
            <label htmlFor={props.id}>{label}</label>
            <input {...field} {...props} />
            {meta.touched && meta.error ? <div>{meta.error}</div> : null}
        </div>
    )
}

上述代码中的…field和…props实践上是为了给input标签上绑定了两种不同的数据,前者来自于formik而后者来自于调用方;

useField钩子函数的履行结果的返回值为field和meta,其中field中包括的是onChange onBlur value这些信息;而meta则包括的是和error相关的过错处理的信息。

下面是自界说组件的运用方式:

<MyIpt label='暗码' type='password' name='password' placeholder='请输入暗码' id='ps' />

09. 封装一个Checkbox自界说标签

// 界说一个名为Checkbox的函数组件,它接纳一个label特点和其他props特点
function Checkbox ({label, ...props}) {
  // 运用Formik的useField钩子来获取一些有用的字段特点和办法
  const [field, meta, helper] = useField(props);
  // 从meta目标中结构出value特点,这将是当时checkbox组组的值
  const { value } = meta;
  // 从helper目标中结构出setValue办法,用于在需求时更新checkbox组的值
  const { setValue } = helper;
  // 界说handleChange函数,此函数将在checkbox的值产生改动时被调用
  const handleChange = () => {
    // 创立一个新的Set实例,它将包括当时的checkbox值
    const set = new Set(value);
    // 检查当时的checkbox项目是否现已选中,假如是,则删去它;假如没有,则增加它
    if (set.has(props.value)) {
      set.delete(props.value); // 假如set中已有相应的值,删去它
    }else {
      set.add(props.value); // 假如set中没有相应的值,增加它
    }
    // 运用setValue来更新checkbox组的值,将Set转为数组
    setValue([...set])
  }
  // 烘托checkbox组件,其中包括了一个input元素和它的标签label
  return (
    <div>
      <label htmlFor="">
        {/* input元素的类型设置为checkbox,checked特点决议了这个checkbox是否被选中 */}
        {/* 运用扩展运算符将props传递给input元素,一起为input设置onChange事情处理函数 */}
        <input checked={value.includes(props.value)} type="checkbox" {...props} onChange={handleChange}/> {label}
      </label>
    </div>
  );
}

上述这段代码界说了一个名为Checkbox的React函数组件,它运用了Formik库的useField钩子。useField钩子用于办理表单字段的状况和更新操作。Checkbox组件旨在处理一个复选框(checkbox)输入,并能够在Formik表单的上下文中正确地更新其值。经过Set来办理选中项的集合,能够有效地切换选中状况且保持选中项的值唯一。组件经过传入的label和props烘托一个复选框和其对应的标签。当复选框的选中状况产生变化时,handleChange函数将被调用,更新复选框的状况到Formik的状况办理中去。

运用上述自界说组件:

    const initialValues = {username: '', hobbies: ['足球', '篮球']};
    <Formik
      initialValues={initialValues}
      onSubmit={handleSubmit}
      validationSchema={schema}
    >
      <Form>
        <Checkbox value="足球" label="足球" name="hobbies"/>
        <Checkbox value="篮球" label="篮球" name="hobbies"/>
        <Checkbox value="橄榄球" label="橄榄球" name="hobbies"/>
        <input type="submit"/>
      </Form>
    </Formik>

进阶用法指南

01. field组件与fieldArray的用法

field组件

  • <Field />组件支撑各种HTML输入元素和自界说组件,便于扩展。

fieldArray组件

  • <FieldArray />组件用于办理动态表单数组,如列表增加、删去操作。

02. 构建高功能表单解决方案

表单功能问题

  • formik的功能应战主要与大型表单和杂乱结构相关。
  • 解决功能问题常常触及削减不必要的烘托。

功能优化策略

  • 运用formik供给的优化东西,如React.memoshouldComponentUpdate
  • 将表单拆分为更小的组件,削减单一组件的杂乱度。

03. 构建高功能表单解决方案进阶

进阶策略

  • 运用formik的<FastField />替代<Field />,针对个别字段进行功能优化。
  • 利用React的useCallbackuseMemo防止不必要的函数重建和计算。

实践案例分析

  • 分析实在世界中的表单应用,如电商网站的结账过程表单。
  • 探讨在不同场景下运用formik进行功能调优的具体情况。