使用Formik轻松开发更高质量的React表单(四)其他几个API解析

2023-05-16

旧话重提



前文中我特别提起Redux Form以及redux-form的问题,我觉得学习Formik你不得不提它们,当然还有它们的「老祖宗」React;既然选择了,那么你必须按照这个方向走下去。有一句叫作“没有最好,只有更好”。这句话应用于开源技术的学习上也很贴切,基于React技术的表单开发,到底哪一种方案最好,相信国内外很多高手都在探讨这个问题。较早的redux-form这个自不必说了,如果你选择而且热恋着redux,那么很不难不注意redux-form,但是redux-form尽管在一定程度上简化了基于redux的表单的开发但是也的确让人觉得很辛苦,这一点从我自己追踪学习redux-form来说就有深刻体会。而现在的Formik开发者也正是体会到了这种痛苦,于是基于前辈们的作者又开发了Formik,并提供口号“Build forms in React, without the tears”——能不能浪漫一些翻译为“React表单不相信眼泪”?(受名片《莫斯科不相信眼泪》诱发)。总之一句话,只有先了解了开发复杂React表单的痛苦你才会深刻体会学习的Formik的必要性。当然,Formik本身也很年轻,只有1岁,版本目前是1.0.2。但是,我相信这个库会很快地发展下去,除非短时间内出现了比Formik更为优秀的React Form解决方案。

<Field />



<Field />会自动把表单中的输入字段「加入」到Formik系统中。它使用name属性匹配Formik中的状态( state)。 <Field />会默认对应一个HTML的 <input />元素。复杂情形下,你可以改变这个底层元素——这可以通过指定此API的component属性的方式实现(这些思路与redux-form都是一致的!)。在此,component属性值可以是一个简单的字符串,如“ select”,也可能是另一个复杂的React组件。当然, <Field /> 还拥有一个很重要的render属性。
下面的代码片断给出了<Field />及其重要属性(component属性和render属性)的典型应用展示。

import React from 'react';
import { Formik, Field } from 'formik';

const Example = () => (
  <div>
    <h1>My Form</h1>
    <Formik
      initialValues={{ email: '', color: 'red', firstName: '' }}
      onSubmit={(values, actions) => {
        setTimeout(() => {
          alert(JSON.stringify(values, null, 2));
          actions.setSubmitting(false);
        }, 1000);
      }}
      render={(props: FormikProps<Values>) => (
        <form onSubmit={props.handleSubmit}>
          <Field type="email" name="email" placeholder="Email" />
          <Field component="select" name="color">
            <option value="red">Red</option>
            <option value="green">Green</option>
            <option value="blue">Blue</option>
          </Field>
          <Field name="firstName" component={CustomInputComponent} />
          <Field
            name="lastName"
            render={({ field /* _form */ }) => (
              <input {...field} placeholder="firstName" />
            )}
          />
          <button type="submit">Submit</button>
        </form>
      )}
    />
  </div>
);

const CustomInputComponent: React.SFC<
  FieldProps<Values> & CustomInputProps
> = ({
  field, // { name, value, onChange, onBlur }
  form: { touched, errors }, // also values, setXXXX, handleXXXX, dirty, isValid, status, etc.
  ...props
}) => (
  <div>
    <input type="text" {...field} {...props} />
    {touched[field.name] &&
      errors[field.name] && <div className="error">{errors[field.name]}</div>}
  </div>
);

字段级校验

思路是使用:validate?: (value: any) => undefined | string | Promise<any>

你可以通过把一个具有校验功能的函数传递给validate属性来执行独立的字段层面的校验。此功能的触发将会相应于在 <Field>的父级组件 <Formik>中指定的validateOnBlur 和validateOnChange配置选项,或者在withFormik方法调用中通过props指定的validateOnBlur 和validateOnChange这两个选项。当然,校验还会对应下面两种情形:

(1)同步情形下,如果校验无效将返回一个包含错误信息的字符串或者干脆返回undefined。典型代码如下:

// Synchronous validation for Field
const validate = value => {
  let errorMessage;
  if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value)) {
    errorMessage = 'Invalid email address';
  }
  return errorMessage;
};

(2)异步情形下,会返回一个能够抛出包含错误信息的字符串异步的Promise对象。这种工作方式类似于Formik提供的validate函数,但不是返回一个errors对象,而仅返回一个字符串。

请参考下面的代码:

// Async validation for Field
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

const validate = value => {
  return sleep(2000).then(() => {
    if (['admin', 'null', 'god'].includes(value)) {
      throw 'Nice try';
    }
  });
};

【注意】考虑到i18n库(实现界面的多语言版本所需要)的使用方面,TypeScript检验类型比较宽松——允许你返回一个函数(例如i18n('invalid'))。

特别提示

当你没有使用定制组件而且你想访问由<Field/>创建的底层的DOM结点(如调用focus)时,你可以通过把回调函数传递给innerRef属性来实现。

<FieldArray />



<FieldArray />这个API本质上是一个有助于实现字段数组或者列表操作的组件。你可以传递给它一个name属性——使其指向包含对应数组的values中的键所在路径。于是,<FieldArray />可以让你通过render这个prop访问数组帮助方法(观察下面代码中的arrayHelpers)。 为了方便起见,调用这些方法就可以触发校验并能管理表单字段的touched信息。

import React from 'react';
import { Formik, Form, Field, FieldArray } from 'formik';

//下面提供的表单示例中有一个可编辑的列表。紧邻每一个输入字段是控制插入与删除的按钮。
//若列表为空,那么会显示一个添加项目的按钮。

export const FriendList = () => (
  <div>
    <h1>Friend List</h1>
    <Formik
      initialValues={{ friends: ['jared', 'ian', 'brent'] }}
      onSubmit={values =>
        setTimeout(() => {
          alert(JSON.stringify(values, null, 2));
        }, 500)
      }
      render={({ values }) => (
        <Form>
          <FieldArray
            name="friends"
            render={arrayHelpers => (
              <div>
                {values.friends && values.friends.length > 0 ? (
                  values.friends.map((friend, index) => (
                    <div key={index}>
                      <Field name={`friends.${index}`} />
                      <button
                        type="button"
                        onClick={() => arrayHelpers.remove(index)} // remove a friend from the list
                      >
                        -
                      </button>
                      <button
                        type="button"
                        onClick={() => arrayHelpers.insert(index, '')} // insert an empty string at a position
                      >
                        +
                      </button>
                    </div>
                  ))
                ) : (
                  <button type="button" onClick={() => arrayHelpers.push('')}>
                    {/* show this when user has removed all friends from the list */}
                    Add a friend
                  </button>
                )}
                <div>
                  <button type="submit">Submit</button>
                </div>
              </div>
            )}
          />
        </Form>
      )}
    />
  </div>
);

name: string

这个属性指向values中相关联的键的名字或者路径。

validateOnChange?: boolean

默认值为true,用来决定在运行任何数组操作后执行还是不执行表单校验。

FieldArray——针对对象数组的使用情形

你还可以遍历一个对象数组——通过使用一种格式为object[index]property或者是object.index.property的方法,它们分别作为<FieldArray />中的 <Field /> 或者<input />元素的name属性的值。请参考下面代码:

<Form>
  <FieldArray
    name="friends"
    render={arrayHelpers => (
      <div>
        {values.friends.map((friend, index) => (
          <div key={index}>
            <Field name={`friends[${index}]name`} />
            <Field name={`friends.${index}.age`} /> // both these conventions do
            the same
            <button type="button" onClick={() => arrayHelpers.remove(index)}>
              -
            </button>
          </div>
        ))}
        <button
          type="button"
          onClick={() => arrayHelpers.push({ name: '', age: '' })}
        >
          +
        </button>
      </div>
    )}
  />
</Form>

FieldArray校验陷阱

当使用<FieldArray>时,进行校验有些值得注意的地方。

第一,如果你使用validationSchema,并且你的表单正好有数组校验需求 (例如一个最小长度值),以及在嵌套数组字段需求情况下,显示错误信息时也需要小心一些——Formik/Yup会在外部显示校验错误信息。例如:

const schema = Yup.object().shape({
  friends: Yup.array()
    .of(
      Yup.object().shape({
        name: Yup.string()
          .min(4, 'too short')
          .required('Required'), // these constraints take precedence
        salary: Yup.string()
          .min(3, 'cmon')
          .required('Required'), // these constraints take precedence
      })
    )
    .required('Must have friends') // these constraints are shown if and only if inner constraints are satisfied
    .min(3, 'Minimum of 3 friends'),
});

既然Yup和你的定制校验函数总会输出字符串形式的错误信息,那么你需要设法确定在显示时是否你的嵌套错误信息是一个数组或者是一个字符串。
于是,为了显示“Must have friends”和“Minimum of 3 friends”(这是我们示例中的数组校验约束)......

不利之处

// within a `FieldArray`'s render
const FriendArrayErrors = errors =>
  errors.friends ? <div>{errors.friends}</div> : null; // app will crash

有利之处

// within a FieldArray's render

const FriendArrayErrors = errors =>
  typeof errors.friends === 'string' ? <div>{errors.friends}</div> : null;

对于嵌套的字段错误信息而言,你应当假定并没有预告定义对象的哪一部分——除非你事先检查了它。这样一来,你可以创建一个定制的<ErrorMessage />组件来帮助实现你的校验,此组件的代码类似如下:

import { Field, getIn } from 'formik';

const ErrorMessage = ({ name }) => (
  <Field
    name={name}
    render={({ form }) => {
      const error = getIn(form.errors, name);
      const touch = getIn(form.touched, name);
      return touch && error ? error : null;
    }}
  />
);
//使用上面定制组件的情形:
<ErrorMessage name="friends[0].name" />; // => null, 'too short', or 'required'

【注意】在Formik v0.12 / 1.0中,支持把一个新的meta属性添加给Field和FieldArray,此属性用于为你提供类似于error和touch这样的相关的元数据信息,这可以使你免于不得不使用Formik或者lodash的getIn方法来检查是否你自己定义了路径部分。

FieldArray帮助函数

下面的帮助函数可以经由render这个属性用来辅助操作字段数组:


  • push: (obj: any) => void: 把一个值添加到数组最后**

  • swap: (indexA: number, indexB: number) => void: 交换数组中的两个值

  • move: (from: number, to: number) => void: 把数组中的一个元素从一个索引位置移动到另一个索引位置

  • insert: (index: number, value: any) => void: 在一个给定索引位置插入一个元素

  • unshift: (value: any) => number: 把一个元素添加到数组开始并返回新的数组长度

  • remove<T>(index: number): T | undefined: 删除指定索引位置的一个元素并返回这个元素

  • pop<T>(): T | undefined: 删除并返回数组尾端的元素**


FieldArray的render方法

有三种方式可以渲染<FieldArray />中包含的内容。请参考下面的代码:

  • <FieldArray name="..." component>

  • <FieldArray name="..." render>

情形一:render: (arrayHelpers: ArrayHelpers) => React.ReactNode

import React from 'react';
import { Formik, Form, Field, FieldArray } from 'formik'

export const FriendList = () => (
  <div>
    <h1>Friend List</h1>
    <Formik
      initialValues={{ friends: ['jared', 'ian', 'brent'] }}
      onSubmit={...}
      render={formikProps => (
        <FieldArray
          name="friends"
          render={({ move, swap, push, insert, unshift, pop }) => (
            <Form>
              {/*... use these however you want */}
            </Form>
          )}
        />
    />
  </div>
);

情况二:当component属性为React组件时

import React from 'react';
import { Formik, Form, Field, FieldArray } from 'formik'

export const FriendList = () => (
  <div>
    <h1>Friend List</h1>
    <Formik
      initialValues={{ friends: ['jared', 'ian', 'brent'] }}
      onSubmit={...}
      render={formikProps => (
        <FieldArray
          name="friends"
          component={MyDynamicForm}
        />
    />
  </div>
);

// 除去数组帮助函数,Formik中的状态和它本身的帮助函数
// (例如values, touched, setXXX, etc)都是经由表单的prop形式提供的
//
export const MyDynamicForm = ({
  move, swap, push, insert, unshift, pop, form
}) => (
 <Form>
  {/**  whatever you need to do */}
 </Form>
);

<Form />



类似于<Field />, <Form />其实也是一个帮助性质的组件(helper component,用于简化表单编写并提高开发效率)。实际上,它是一个围绕<form onSubmit={context.formik.handleSubmit} />实现的包装器。这意味着,你不需要显式地书写<form onSubmit={props.handleSubmit} />——如果你不想干的话。

只围绕ReactDOM的使用情形

import React from 'react';
import { Formik, Field, Form } from 'formik';

const Example = () => (
  <div>
    <h1>My Form</h1>
    <Formik
      initialValues={{ email: '', color: 'red' }}
      onSubmit={(values, actions) => {
        setTimeout(() => {
          alert(JSON.stringify(values, null, 2));
          actions.setSubmitting(false);
        }, 1000);
      }}
      component={MyForm}
    />
  </div>
);

const MyForm = () => (
  <Form>
    <Field type="email" name="email" placeholder="Email" />
    <Field component="select" name="color">
      <option value="red">Red</option>
      <option value="green">Green</option>
      <option value="blue">Blue</option>
    </Field>
    <button type="submit">Submit</button>
  </Form>
);

withFormik(options)



此方法用于构建一个高阶React组件类,该类把props和form handlers (即"FormikBag")传递进你的根据提供的选项生成的组件中。

重要options成员解析


(1)displayName?: string

在你的内部表单组件是一个无状态函数组件情况下,你可以使用displayName这个选项来给组件一个合适的名字——从而从React DevTools(调试工具,在我以前的博客中专门讨论过)中可以更容易地观察到它。如果指定了这个属性,你的包装表单中将显示成这样——Formik(displayName)。如果忽略这个属性,显示样式为Formik(Component)。不过,这个选项对于类组件(例如class XXXXX extends React.Component {..})并不必要。

(2)enableReinitialize?: boolean

默认为false。这个属性用来控制当包装组件属性变化(使用深度相等比较,using deep equality)时Formik是否应当复位表单。

(3)handleSubmit: (values: Values, formikBag: FormikBag) => void

这是表单提交处理器。其中的参照是描述你的表单的values对象,还有“FormikBag”。其中,FormikBag:(a)包含一个对象,此对象拥有被注入的属性和方法的子集(如所有类似于set<Thing>格式的方法,还有方法resetForm);(b)包含任何属性——这些属性都将被传递给包装的组件。

(4)The "FormikBag":

  • props (传递给包装组件的props)
  • resetForm
  • setErrors
  • setFieldError
  • setFieldTouched
  • setFieldValue
  • setStatus
  • setSubmitting
  • setTouched
  • setValues
    【注意】errors,touched,status及所有的事件处理器都没有包含在FormikBag中。

(5)isInitialValid?: boolean | (props: Props) => boolean

默认为 false. 此选择用于控制表单加载前isValid属性的初始值。你还可以传递一个函数。 Useful for situations when you want to enable/disable a submit and reset buttons on initial mount.

(6)mapPropsToValues?: (props: Props) => Values

If this option is specified, then Formik will transfer its results into updatable form state and make these values available to the new component as props.values. If mapPropsToValues is not specified, then Formik will map all props that are not functions to the inner component's props.values. That is, if you omit it, Formik will only pass props where typeof props[k] !== 'function', where k is some key.

Even if your form is not receiving any props from its parent, use mapPropsToValues to initialize your forms empty state.

(7)validate?: (values: Values, props: Props) => FormikErrors<Values> | Promise<any>

【注意】Formik作者极力推荐使用validationSchema与Yup进行表单校验。但是,就校验这个任务而言,你可以任意选择自己喜欢的直观高效的校验方案。

使用函数校验表单的values对象。这个函数可能是下面两种情形之一:

(A)同步函数,并且返回一个对象errors。
// Synchronous validation
const validate = (values, props) => {
  let errors = {};

  if (!values.email) {
    errors.email = 'Required';
  } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
    errors.email = 'Invalid email address';
  }

  //...

  return errors;
};

(B)异步函数,它返回一个包含errors对象的Promise。

// Async Validation
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

const validate = (values, props) => {
  return sleep(2000).then(() => {
    let errors = {};
    if (['admin', 'null', 'god'].includes(values.username)) {
      errors.username = 'Nice try';
    }
    // ...
    if (Object.keys(errors).length) {
      throw errors;
    }
  });
};

(8)validateOnBlur?: boolean

默认为true。在blur事件触发时(更具体一些说,是当调用handleBlur,setFieldTouched或者是setTouched时)使用这个选项进行校验。

(9)validateOnChange?: boolean

默认为true。 通过此选项告诉Formik在change事件或者相关方法(更具体一些说,是当调用handleChange,setFieldValue或者setValues)触发时进行校验。

(10)validationSchema?: Schema | ((props: Props) => Schema)

这个属性极为重要,它定义了一个Yup模式( schema)或者是返回Yup模式的一个函数。在校验是使用这个属性是非常有用的。错误信息被映射到内部组件的errors对象。它的键应当匹配values中对应的键。

注入属性与方法

这些与<Formik render={props => ...} />是一致的。

在Formik中使用connect()



connect()是一个高阶组件,它用于把原始的Formik上下文以属性方式(命名为formik)注入到内部组件中。另外一个有趣的事实是:Formik在底层上也利用了connect()来封装<Field/>,<FastField>和<Form>。因此,在开发定制组件时很有经验的程序员可能会发现connect()还是很有用的。请参考下面的代码了解这个函数的基本用法:

import { connect } from 'formik';

const SubmitCount = ({ formik }) => <div>{formik.submitCount}</div>;

export default connect(SubmitCount);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用Formik轻松开发更高质量的React表单(四)其他几个API解析 的相关文章

  • 软件需求工程与UML建模第二周工作总结

    项目范围 xff1a 1 能够实现仅弹道技能的躲避训练和带有技能发射主体的技能躲避训练 2 要能够玩家自由选择角色进行训练 3 要能够实现包含技能躲避 1v1对线训练等多模式选择的训练方式 4 要能够快捷进行多次练习 xff0c 我们计划加
  • 阻塞和非阻塞~

    很清楚 先记下 https www zhihu com question 19732473 answer 14413599 转载于 https www cnblogs com Mickey697 p 10863679 html
  • vnc利用ps命令查看所有DISPLAY

    ps aux grep vnc 使用该命令可以看到详细的vnc进程和使用的DISPLAY和DISPLAY的分辨率
  • 基础数据类型的补充,编码的进阶,基础数据类型之间的转换

    1 内容总览 基础数据类型的补充数据类型之间的转换 其他数据类型转成bool值为False的情况编码的进阶 2 具体内容 数据类型的补充 str 6个 code str xff1a 补充的方法练习一遍就行 6个 s1 61 39 taiBA
  • Keepalived

    Keepalived双机热备 Keepalived简介 Keepalived是使用C语言编写的路由热备软件 xff0c 该项目软件的主要目标是为Linux系统提供简单高效的负载均衡及高可用解决方案 负载均衡架构依赖于知名的IPVS xff0
  • Scyther 形式化分析工具资料整理(三)

    1 作者Cas Cremers在做TLS1 3的时候我么发现并没有使用Scyther 形式化丰分析工具对其进行分析 xff0c 而是使用了 The Tamarin 作者建立了TLS 13的模型 那么我的目标是 使用Scyther工具对TLS
  • java产生随机数的三种方式

    public class Test public static void main String args Random类 创建随机数对象有2种 一种是添加参数 也叫种子 这种方式创建出来的数 刷新后不会改变 相当于常量了 主要方法 nex
  • gcc 编译两个so其中soA依赖soB

    有两个so xff0c 其中soB中调用soA xff1b 那么我们打包soB的时候连接soA xff1b 在打包test程序的时候连接soB 此时soB会自动查找依赖的soA xff1b 如下测试 在编译之前指定环境变量 xff1a ex
  • Vue 循环 [Vue warn]: Avoid using non-primitive value as key

    页面中不添加 xff1a key 索引的时候 xff0c 会不停的提示虚线 xff0c 但不影响使用 后来加了一个索引 xff0c 加成了 key 61 34 content 34 从后台取出来的contents是一个list xff0c
  • 博客系统 01 登录退出

    一 工程搭建 使用的是IDEA xff08 1 xff09 新建个动态web工程 xff08 Blog xff09 xff08 2 xff09 导入jar包 xff08 SSH jar包 xff09 xff08 3 xff09 导入配置文件
  • 蓝桥杯2017国赛JAVAB组 树形显示 题解

    标题 xff1a 树形显示 对于分类结构可以用树形来形象地表示 比如 xff1a 文件系统就是典型的例子 树中的结点具有父子关系 我们在显示的时候 xff0c 把子项向右缩进 xff08 用空格 xff0c 不是tab xff09 xff0
  • 读《【解密】京东B2B业务架构演变》有感

    京东的B2B业务目前来说发展比较好 xff0c 它的定位是让各类型的企业都可以在京东的 B 平台上进行采购 建立采购关系 京东 B2B 的用户群体主要分为 2 类 xff0c 一类是大 B 用户 另一类是小 B 用户 比如联通 移动公司跟京
  • python中线程、进程和协程的区别

    进程是资源分配的单位线程是操作系统调度的单位协程 xff0c 又称微线程 xff0c 纤程 xff0c 协程的切换只是单纯的操作CPU的上下文 xff0c 资源很小 xff0c 效率高进程切换需要的资源很最大 xff0c 效率很低一个程序至
  • linux下常用alias

    alias xx 61 39 39 其中 61 两边不要有空格
  • C#常用控件(2)

    1 Botton 控件 按钮用图片应该设置内阁为Image xff0c 而不能设置Background为Image xff0c 如果只设置背景 xff0c 按钮鼠标经过样式还在 XAML写法 C 写法 2 Combobox 控件 下拉框控件
  • Django 路由层 虚拟环境下建项目

    路由匹配规律 第一个参数是正则表达式 xff0c 匹配规则按照从上往下一次匹配 xff0c 匹配到一个之后立即匹配 xff0c 直接执行对应的视图函数 urlpatterns 61 url r 39 admin 39 admin site
  • 磁盘显示设备未就绪,要怎么找到资料

    设备未就绪说明这个盘的文件系统结构损坏了 在平时如果数据不重要 xff0c 那么可以直接格式化就能用了 但是有的时候里面的数据很重要 xff0c 那么就必须先恢复出数据再格式化 具体恢复方法可以看正文了解 xff08 不格式化的恢复方法 x
  • centos7下安装vnc更改vnc默认端口号

    应用场景 xff1a 某些情景下 xff0c 需要用的linux的桌面环境 xff0c Ubuntu的桌面性能在linux发行版中算是数一数二的 xff0c 如果不熟悉Debian系统 xff0c Centos RHEL系列也行 xff1b
  • STM32-USB学习笔记(一) USB基础

    USB基础知识扫盲 前言 本文将从USB的 插入检测 身份识别 数据传输三个方面对USB通讯整个过程扫盲 xff0c 其中有些知识点的详细信息会放在文章最下面的附录中供查看 xff0c 从而保证文章的整体简洁 在进入主题之前 xff0c 首
  • VNC连接linux下vmware虚拟机win-server的分辨率设置

    最近用dell的r610装了rhel搞了几个虚拟机玩 xff0c 系统装的是2k3 xff0c 发现用3389连虚拟机的时候 xff0c 分辨率是跟本地一致的1280 1024 xff0c 用vnc连就是1024 768 xff0c 觉得奇

随机推荐

  • 基于maven maven-replacer-plugin 插件对JS,CSS统一加版本号

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 基于maven对JS xff0c CSS统一加版本号 在写WEB应用的时候 xff0c 每次对JS CSS文件做的修改 xff0c 对于用户来说 xff0c 都很郁闷 xf
  • 【树莓派】树莓派上刷android系统

    1 首先将下载的 andrpi3 20160626 img bz2 文件解压 xff0c 可以获得一个 IMG光盘映像文件 xff08 7G多 xff09 xff1b 2 准备1张16G TF卡 xff0c 插入电脑 xff0c 然后运行W
  • 如何应对“需求不确定型项目”?

    问题描写叙述 xff1a 需求不确定 老板直接和客户谈需求 xff0c 项目经理不能或不方便參与 xff0c 打下手 这类项目如何办 xff1f 要深层次了解客户的想法 xff0c 各种利益 xff0c 地盘等 xff0c 这非常难做得到吧
  • 利用CH341A编程器刷新BIOS,恢复BIOS,妈妈再也不用担心BIOS刷坏了

    前几天 xff0c 修电脑主析就捣鼓刷BIOS xff0c 结果刷完黑屏开不了机 xff0c 立刻意识到完了 xff0c BIOS刷错了 就从网上查资料 xff0c 各种方法试了个遍 xff0c 什么用处都没有 终于功夫不负有心人 xff0
  • STM32-串口通信(串口的接收和发送)

    文章目录 STM32的串口通信一 STM32里的串口通信二 串口的发送和接收串口发送串口接收 三 串口在STM32中的配置四 串口接收的两种实现方式1 需要更改的地方2 查询RXNE标志位3 使用中断 总结 STM32的串口通信 本文在于记
  • 技术干货|深入理解flannel

    根据官网的描述 xff0c flannel是一个专为kubernetes定制的三层网络解决方案 xff0c 主要用于解决容器的跨主机通信问题 1 概况 首先 xff0c flannel利用Kubernetes API或者etcd用于存储整个
  • Windows操作系统产品名与内部版本号的对应

    虽然Windows的命名取决于很多因素 xff0c 形式各不相同 xff0c 但是其内部版本号却是一脉相承的 xff0c 从最初的Windows 1 0到之后的Windows 2 0 Windows 3 0 xff0c 再到Windows
  • webpack + jquery + bootstrap 环境配置

    nodejs环境请自行谷歌百度 1 先安装vue cli脚手架 xff1a npm install vue cli g 2 创建项目 xff0c 此处项目名以test为例 xff1a vue init webpack simple test
  • 刚刚,OpenStack 第 19 个版本来了,附28项特性详细解读!

    刚刚 xff0c OpenStack 第 19 个版本来了 xff0c 附28项特性详细解读 xff01 OpenStack Stein版本引入了新的多云编排功能 xff0c 以及帮助实现边缘计算用例的增强功能 OpenStack由一系列相
  • Linux VNC server 安装配置

    1 安装vnc server root 64 pxe yum install tigervnc server y 2 设置 vnc server 开机启动 root 64 pxe chkconfig vncserver on 3 修改vnc
  • 常用非关系型数据库产品介绍

    1 memcache memcache xff08 键值型数据库 xff09 memcache是把访问的数据存在内存里面 xff0c 外部访问现在内存里面找 xff0c 找不到再从数据库里面找 xff0c 可以减轻数据库的压力 xff0c
  • Webpack 4.X 从入门到精通 - devServer与mode(三)

    上一篇文章里详细介绍了一下插件的用法 xff0c 这一篇文章接着丰富module exports里的属性 如今的前端发展已经非常迅速了 xff0c 伴随而来的是开发模式的转变 现在已经不再是写个静态页面并放在浏览器里打开预览一下了 在实际的
  • 块状元素与内联元素的区别

    css中块状元素是一个重要的知识点 xff0c css下height和width不起作用使我们经常遇到的问题 xff0c 这就需要我们正确区分块状元素和内联元素 块状元素和内联元素的区分很简单 xff0c 我们只需要注意html元素是否排斥
  • vsftp 锁定用户目录

    vsftp 安装以后给用户权限和锁定目录 xff1b 关闭SELinux xff1a 修改 etc selinux config文件中的SELINUX 61 34 34 为 disabled xff0c 然后重启 如果不想重启系统 xff0
  • 解决使用WinScp连接Ubantu系统失败的问题---SSH无法连接

    起因 为了互通Linux系统和Windows系统的文件 xff0c 以更好的实现文件管理和资源共享 所以在查阅资料后 xff0c 使用WinScp xff0c WinSCP是一个Windows环境下使用SSH的开源图形化SFTP客户端 它的
  • 一文让你明白CPU上下文切换

    我们都知道 xff0c Linux 是一个多任务操作系统 xff0c 它支持远大于 CPU 数量的任务同时运行 当然 xff0c 这些任务实际上并不是真的在同时运行 xff0c 而是因为系统在很短的时间内 xff0c 将 CPU 轮流分配给
  • HBase shell scan 过滤器用法总结

    比较器 xff1a 前面例子中的regexstring 2014 11 08 binary x00 x00 x00 x05 xff0c 这都是比较器 HBase的filter有四种比较器 xff1a xff08 1 xff09 二进制比较器
  • [Ubuntu] LightDM 轻量级桌面显示管理器

    LightDM xff08 Light Display Manager xff09 是一个全新的轻量级 Linux 桌面显示管理器 xff0c 而传统的 Ubuntu 是使用 GNOME 桌面标准的 GDM LightDM 是一个跨桌面显示
  • 算法笔记--区间素数筛

    筛 l r 之间的合数 l lt 61 r lt 61 1e12 r l lt 61 1e6 筛小于等于r的合数所需的质因子大小最多不会超过根号r xff08 lt 61 1e6 xff09 模板 const int N 61 1e6 43
  • 使用Formik轻松开发更高质量的React表单(四)其他几个API解析

    旧话重提 前文中我特别提起Redux Form以及redux form的问题 xff0c 我觉得学习Formik你不得不提它们 xff0c 当然还有它们的 老祖宗 React xff1b 既然选择了 xff0c 那么你必须按照这个方向走下去