Yup & PropType 整理

3,413 阅读7分钟


内容简介

本文主要记录,PropsTypes & yup的日常使用


PropType

PropTypes 提供一系列验证器,可用于确保组件接收到的数据类型是有效的。在本例中, 我们使用了 PropTypes.string。当传入的 prop 值类型不正确时,JavaScript 控制台将会显示警告。出于性能方面的考虑,propTypes 仅在开发模式下进行检查。

安装

npm i prop-types


检验器对应类型

App.propTypes = {
    // 你可以将属性声明为 JS 原生类型,默认情况下
  // 这些属性都是可选的。
  optionalArray: PropTypes.array,// 数组
  optionalBool: PropTypes.bool,// true,false
  optionalFunc: PropTypes.func,// 方法
  optionalNumber: PropTypes.number,// 数值
  optionalObject: PropTypes.object,// 对象
  optionalString: PropTypes.string,// 字符串
  optionalSymbol: PropTypes.symbol,// Symbel

  // 任何可被渲染的元素(包括数字、字符串、元素或数组)
  // (或 Fragment) 也包含这些类型。
  optionalNode: PropTypes.node,

  // 一个 React 元素。
  optionalElement: PropTypes.element,

  // 一个 React 元素类型(即,MyComponent)。
  optionalElementType: PropTypes.elementType,

  // 你也可以声明 prop 为类的实例,这里使用
  // JS 的 instanceof 操作符。
  optionalMessage: PropTypes.instanceOf(Message),//必须是 Message的实例

  // 你可以让你的 prop 只能是特定的值,指定它为
  // 枚举类型。
  optionalEnum: PropTypes.oneOf(['News', 'Photos']),// 必须是 其中一个数值,否在报错

  // 一个对象可以是几种类型中的任意一个类型
  optionalUnion: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.number,
    PropTypes.instanceOf(Message)
  ]),

  // 可以指定一个数组由某一类型的元素组成
  optionalArrayOf: PropTypes.arrayOf(PropTypes.number),

  // 可以指定一个对象由某一类型的值组成
  optionalObjectOf: PropTypes.objectOf(PropTypes.number),

  // 可以指定一个对象由特定的类型值组成
  optionalObjectWithShape: PropTypes.shape({// 表示这个 对象只有 color 和 fontsize属性
    color: PropTypes.string,
    fontSize: PropTypes.number
  }),
  
  // 对象具有额外属性时警告
  optionalObjectWithStrictShape: PropTypes.exact({
    name: PropTypes.string,
    quantity: PropTypes.number
  }),   
  // 例如
 function Foo({ foo, bar }) {
  return <div>{foo}{bar}</div>
}
Foo.propTypes = exact({
  foo: PropTypes.string,
  bar: PropTypes.number,
});
<Foo foo="hi" bar={3} /> // no warnings
<Foo foo="hi" bar={3} baz="extra" /> // propTypes warning!


  // 你可以在任何 PropTypes 属性后面加上 `isRequired` ,确保
  // 这个 prop 没有被提供时,会打印警告信息。
  requiredFunc: PropTypes.func.isRequired,

  // 任意类型的数据
  requiredAny: PropTypes.any.isRequired,

  // 你可以指定一个自定义验证器。它在验证失败时应返回一个 Error 对象。
  // 请不要使用 `console.warn` 或抛出异常,因为这在 `onOfType` 中不会起作用。
  customProp: function(props, propName, componentName) {
    if (!/matchme/.test(props[propName])) {
      return new Error(
        'Invalid prop `' + propName + '` supplied to' +
        ' `' + componentName + '`. Validation failed.'
      );
    }
  },

  // 你也可以提供一个自定义的 `arrayOf` 或 `objectOf` 验证器。
  // 它应该在验证失败时返回一个 Error 对象。
  // 验证器将验证数组或对象中的每个值。验证器的前两个参数
  // 第一个是数组或对象本身
  // 第二个是他们当前的键。
  customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
    if (!/matchme/.test(propValue[key])) {
      return new Error(
        'Invalid prop `' + propFullName + '` supplied to' +
        ' `' + componentName + '`. Validation failed.'
      );
    }
  })
};


限制单个元素

你可以通过 PropTypes.element 来确保传递给组件的 children 中只包含一个元素,只要类型之后 带有 isRequired都表示 限制单个元素


class App extends React.Component {
  render() {
    // 这必须只有一个元素,否则控制台会打印警告。
    const children = this.props.children;
    return (
      <div>
        {children}
      </div>
    );
  }
}

App.propTypes = {
  children: PropTypes.element.isRequired,// 此处表示只能 拥有一个元素
  router: PropTypes.object.isRequired,// 只能有一个对象载入 router
};


设置默认值

可以通过赋值特定的 defaultProps 属性为 props 定义默认值


class Greeting extends React.Component {
  render() {
    return (
      <h1>Hello, {this.props.name}</h1>// dhyuan
    );
  }
}

// 指定 props 的默认值:
Greeting.defaultProps = {
  name: 'dhyuan'
};

// 渲染出 "Hello, Stranger":
ReactDOM.render(
  <Greeting />,
  document.getElementById('example')
);


Yup

Yup是用于值解析和验证的JavaScript模式构建器。定义模式,转换值以匹配,验证现有值的形状或两者。Yup模式具有极强的表现力,可以建模复杂的,相互依赖的验证或值转换;一般用于formik的表达检测


安装

// 如果你是要 javascript
  npm install -S yup
  or
  yarn add yup
// 如果你是要 typrscript
  npm install -D @types/yup



API解释

let yup = require('yup');

yup.mixed;
yup.string;
yup.number;
yup.boolean; // also aliased as yup.bool
yup.date;
yup.object;
yup.array;

// 对于嵌套模式,yup.reach将基于提供的路径检索嵌套模式
yup.reach;

// 向核心架构类型添加新方法。一种友好的方便方法schemaType.prototype[name] = method
yup.addMethod;

// 创建对另一个同级或同级后代字段的引用。引用在验证/广播时解析,并在指定的位置提供支持。
// 以正确的顺序评估Ref,以便在使用Ref之前在字段之前解析Ref值(注意循环依赖性!)
yup.ref;

// 创建在验证/广播时评估的架构。对于创建多态字段和数组的树之类的递归模式很有用。
//警告!当定义父子递归对象模式,你想重置default() 到undefined孩子,否在无限递归自己
yup.lazy;


yup.setLocale;
yup.ValidationError;

使用

let yup = require('yup');

let schema = yup.object().shape({
  name: yup.string().required(),// name : 字符串,非空
  age: yup
    .number()// 数值类型
    .required()// 非空
    .positive()// 绝对值
    .integer(),// 整型
  email: yup.string().email(),// 字符串, 邮箱格式
  website: yup.string().url(),// 字符串, url格式
  createdOn: yup.date().default(function() {
    return new Date();// 日期格式,默认值为今天日期
  }),
});

// check validity
schema
  .isValid({
    name: 'jimmy',
    age: 24,
  })
  .then(function(valid) {
    valid; // => true
  });

// you can try and type cast objects to the defined schema
schema.cast({
  name: 'jimmy',
  age: '24',
  createdOn: '2014-09-23T19:25:25Z',
});
// => { name: 'jimmy', age: 24, createdOn: Date }


string使用

let schema = yup.string();
await schema.isValid('hello'); // => true, 验证 'hello' 是否时字符串

yup.string.required // 不能为空,或不能缺失值
yup.string.length // 设置 属性的固定长度,如果不是该长度报错
yup.string.min // 设置字符串值的最小长度限制
yup.string.max // 设置字符串值的最大长度限制
yup.string.matches // 提供一个任意regex值以匹配该值

        let schema = string().matches(/(hi|bye)/);
        await schema.isValid('hi'); // => true
        await schema.isValid('nope'); // => false

// 表示允许匹配空值
yup.string.matches(regex: Regex, options: { message: string, excludeEmptyString: bool })
        
        let schema = string().matches(/(hi|bye)/, { excludeEmptyString: true });
        await schema.isValid(''); // => true

yup.string.email // 验证必须为邮箱
yup.string.url // 通过正则表达式将该值验证为有效的URL
yup.string.ensure // 变换undefined和null值设置为空字符串设定一起default为空字符串
yup.string.trim // 通过删除开头和结尾的空格来转换字符串值
yup.string.lowercase // 将字符串值转换为小写
yup.string.uppercase // 将字符串值转换为大写


number使用

let schema = yup.number();
await schema.isValid(10); // => true, 验证 10 是否时数值
// 默认cast逻辑number是:parseFloat

yup.number.required // 不能为空,或不能缺失值
yup.number.length // 设置 属性的固定长度,如果不是该长度报错
yup.number.min // 设置允许的最小值
yup.number.max // 设置允许的最大值
yup.number.lessThan // 值必须小于
yup.number.moreThan // 值必须大于
yup.number.positive // 值必须为正数
yup.number.negative // 值必须为负数
yup.number.integer // 验证数字是整数
yup.number.truncate // 通过去除小数点右边的数字来将值强制转换为整数
yup.number.round // 四舍五入的整数
yup.number.ciel // 向上取整
yup.number.floor // 向下取整



date使用

let schema = yup.date();
await schema.isValid(new Date()); // => true, 验证 是否是日期 

yup.date.min // 设置允许的最短日期

yup.date.max // 设置允许的最大日期


array使用

let schema = yup.array();
await schema.isValid([1, 2]); // => true, 验证 是否是 数组

yup.array.of // 指定数组元素的架构
yup.array.required // 不允许为空数组
yup.array.min  // 设置数组的最小长度限制
yup.array.max // 设置数组的最大长度限制

// 通过将默认值设置为[]并且将null和undefined值也转换为空数组,
// 确保该值是一个数组。任何非空的非数组值都将包装在数组中
yup.array.ensure 
   
  array()
  .ensure()
  .cast(null); // => []

  array()
    .ensure()
    .cast(1); // => [1]

  array()
    .ensure()
    .cast([1]); // => [1]

yup.array.compact // 从数组中删除虚假值。提供拒绝功能可让您自己指定拒绝标准

   array().compact().cast(['', 1, 0, 4, false, null]); // => [1, 4]


object使用

定义对象架构。传入的选项isValid也将传递给子模式。支持与相同的所有方法mixed

yup.object().shape({
  name: string().required(),
  age: number()
    .required()
    .positive()
    .integer(),
  email: string().email(),
  website: string().url(),
});



object().shape({
  num: number(),
});
// or
object({
  num: number(),
});


// 定义对象的键和所述键的模式。请注意,您可以链接shape方法,其作用类似于对象扩展
yup.object.shape 

yup.object({
  a: string(),
  b: number(),
}).shape({
  b: string(),
  c: number(),
});

// or

yup.object({
  a: string(),
  b: string(),
  c: number(),
});

// 将指定的键转换为新键。如果第三个参数【alias】为,true 则将保留旧key
yup.object.from

let schema = object({
  myProp: mixed(),
  Other: mixed(),
}).from('prop', 'myProp').from('other', 'Other', true);
// prop - > myProp ; myProp: 5
// 第二个 因为aliastrue, 所以 不转换,直接添加新key 并把值加入进去 : other: 6, Other: 6
schema.cast({ prop: 5, other: 6 }); // => { myProp: 5, other: 6, Other: 6 }

// 验证对象值仅包含中指定的键shape,false作为第一个参数传递,
// 以禁用检查。stripUnknown在非严格模式下,将键限制为已知,也会启用选项。
yup.object.noUnknown