目录
(3)、检测 react 元素及其类型——element / elementType
(4)、arrayOf 实现数组的多重嵌套检测(元素类型只能相同)
(5)、objectOf 实现对象多重嵌套检测(元素类型只能相同)
(6)、instanceOf 检测 prop 是不是指定类的 prop
(1)、class 组件中使用 PropTypes 进行类型检查
前言
在开发过程中,往往需要对整个应用程序做类型检查。你可以使用 Flow 或 TypeScript 等 JavaScript 扩展来实现。
当然,如果你使用的是 React,也可以使用其内置的 PropTypes 进行类型检查。使用前必须先安装 prop-types 插件。
一、安装 prop-types 插件
npm install prop-types -S
二、PropTypes 的规则
1、PropTypes 的一系列验证
(1)、检测 JS 原生类型
static propTypes={
love: PropTypes.array,
isAdult: PropTypes.bool,
ability: PropTypes.func,
age: PropTypes.number,
subjects: PropTypes.object,
name: PropTypes.string,
secret: PropTypes.symbol,
}
(2)、检测任何元素
static propTypes={
str: PropTypes.node,
}
(3)、检测 react 元素及其类型——element / elementType
/** 假设有一个自定义的 react 组件叫做 MyComponent。 **/
// 一个 React 元素
static propTypes={
MyComponent: PropTypes.element,
}
// 一个 React 元素类型
static propTypes={
MyComponent: PropTypes.elementType,
}
限制单个元素:通过 PropTypes.element.isRequired 来确保传递给组件的 children 中只包含一个元素。
import PropTypes from 'prop-types';
class MyComponent extends React.Component {
render() {
// 这必须只有一个元素,否则控制台会打印警告。
const children = this.props.children;
return (
<div>
{children}
</div>
);
}
}
MyComponent.propTypes = {
children: PropTypes.element.isRequired
};
(4)、arrayOf 实现数组的多重嵌套检测(元素类型只能相同)
// 可以指定一个数组由某一类型的元素组成
optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
(5)、objectOf 实现对象多重嵌套检测(元素类型只能相同)
// 可以指定一个对象由某一类型的值组成
optionalObjectOf: PropTypes.objectOf(PropTypes.number),
(6)、instanceOf 检测 prop 是不是指定类的 prop
// 使用 instanceof 操作符声明 prop 为指定类的实例
// 假设指定的类为 Message
optionalMessage: PropTypes.instanceOf(Message),
(7)、oneOf 明确值检测通过
// 为 prop 指定特定的值
optionalEnum: PropTypes.oneOf(['News', 'Photos']),
(8)、oneOfType 多种类型检测通过
// 一个对象可以是几种类型中的任意一个类型
optionalUnion: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.instanceOf(Message)
]),
(9)、shape 检测不同对象的不同属性的不同数据类型
弥补了 arrayOf 和 objectOf 的不足,可用于检测 元素多类型(元素类型不同) 的对象或数组。
// 可以指定一个对象由特定的类型值组成
static propTypes = {
object: PropTypes.shape({
name: PropTypes.string,
age: PropTypes.number
})
}
(10)、exact 检测是否有指定的额外属性存在
// 具有额外属性警告的对象
optionalObjectWithStrictShape: PropTypes.exact({
name: PropTypes.string,
quantity: PropTypes.number
}),
2、isRequired 设置必须数据
// 你可以在任何 PropTypes 属性后面加上 `isRequired` ,确保
// 这个 prop 没有被提供时,会打印警告信息。
requiredFunc: PropTypes.func.isRequired,
// 任意类型的必需数据
requiredAny: PropTypes.any.isRequired,
3、defaultProps 设置 Prop 默认值
class Greeting extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
// 指定 props 的默认值:
Greeting.defaultProps = {
name: 'Stranger'
};
// 渲染出 "Hello, Stranger":
ReactDOM.render(
<Greeting />,
document.getElementById('example')
);
4、react 官方给出的使用文件
import PropTypes from 'prop-types';
MyComponent.propTypes = {
// 你可以将属性声明为 JS 原生类型,默认情况下
// 这些属性都是可选的。
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol,
// 任何可被渲染的元素(包括数字、字符串、元素或数组)
// (或 Fragment) 也包含这些类型。
optionalNode: PropTypes.node,
// 一个 React 元素。
optionalElement: PropTypes.element,
// 一个 React 元素类型(即,MyComponent)。
optionalElementType: PropTypes.elementType,
// 你也可以声明 prop 为类的实例,这里使用
// JS 的 instanceof 操作符。
optionalMessage: PropTypes.instanceOf(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: PropTypes.string,
fontSize: PropTypes.number
}),
// An object with warnings on extra properties
optionalObjectWithStrictShape: PropTypes.exact({
name: PropTypes.string,
quantity: PropTypes.number
}),
// 你可以在任何 PropTypes 属性后面加上 `isRequired` ,确保
// 这个 prop 没有被提供时,会打印警告信息。
requiredFunc: PropTypes.func.isRequired,
// 任意类型的必需数据
requiredAny: PropTypes.any.isRequired,
// 你可以指定一个自定义验证器。它在验证失败时应返回一个 Error 对象。
// 请不要使用 `console.warn` 或抛出异常,因为这在 `oneOfType` 中不会起作用。
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 验证异常时的信息
语法:
Son.propTypes = {
prop: function(props, propName, componentName){
if(/*判断条件*/){
return new Error(/*错误的参数*/)
}
}
}
比如:
/**
* 你可以指定一个自定义验证器。它在验证失败时应返回一个 Error 对象。
* 请不要使用 `console.warn` 或抛出异常,因为这在 `oneOfType` 中不会起作用。
**/
export function customProp (props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error(
'Invalid prop `' + propName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
}
/**
* 你也可以提供一个自定义的 `arrayOf` 或 `objectOf` 验证器。
* 它应该在验证失败时返回一个 Error 对象。
* 验证器将验证数组或对象中的每个值。验证器的前两个参数:
* · 是数组或对象本身;
* · 是他们当前的键。
**/
export function customArrayProp () {
return 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 的使用
PropTypes 提供一系列验证器,用来确保组件接收到的数据类型是有效的。当传入的 prop 值类型不正确时,JavaScript 控制台将会显示警告。出于性能方面的考虑,PropTypes 仅在开发模式下进行检查。
1、ES6 中旧的使用方式
import { PureComponent } from 'react';
import PropTypes from 'prop-types';
class Greeting extends PureComponent {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
// 指定 props 的默认值
Greeting.defaultProps = {
name: 'Stranger'
};
// 渲染 "Hello, Stranger":
ReactDOM.render(
<Greeting />,
document.getElementById('example')
);
2、ES7 新的使用方式(推荐)
ES7 中引入了创建静态变量的方式——使用 static 关键字。
(1)、class 组件中使用 PropTypes 进行类型检查
import { PureComponent } from 'react';
import PropTypes from 'prop-types';
class Greeting extends PureComponent {
//如果没有传递该属性时的默认值
static defaultProps = {
name: 'stranger'
}
//如果传递该属性,该属性值必须为字符串
static propTypes={
name: PropTypes.string
}
render() {
return (
<div>Hello, {this.props.name}</div>
)
}
}
(2)、函数组件中使用 PropTypes 进行类型检查
import PropTypes from 'prop-types'
function HelloWorldComponent({ name }) {
return (
<div>Hello, {name}</div>
)
}
HelloWorldComponent.propTypes = {
name: PropTypes.string
}
export default HelloWorldComponent;
【拓展】
由 React.memo
/ React.forwardRef
创建的组件,也可以使用 PropTypes 进行类型检查。
五、典型案例
案例一:
import React from 'react';
import ReactDom from 'react-dom';
import propsTypes from 'prop-types';
/**
* 可以放在类外(ES6)
* // 类型约定
* App.propTypes={
* num: propsTypes.number,
* title: propsTypes.string.isRequired//必传参数
* };
* // 默认值
* App.defaultProps={//类属性|静态属性
* arr:[],
* };
**/
class App extends React.Component{
/** 可以放在类内(ES7)**/
// 类型约定
static propTypes={
num: propsTypes.number,
title: propsTypes.string.isRequired//必传参数
};
// 默认值
static defaultProps = {
arr:[],
};
render(){
return (
<div>
<h3>props类型检查{this.props.title}</h3>
{this.props.arr}
<hr/>
{
this.props.arr.map((val, index) => (
<li key={index}>{val}</li>
))
}
<hr/>
{this.props.num + 9}
</div>
)
}
}
ReactDom.render(
<App title2={"qq"} num={123}/>,
document.querySelector("#root")
);
本文参考资料:
https://www.npmjs.com/package/prop-types
https://cloud.tencent.com/developer/article/1684723
https://segmentfault.com/a/1190000016182458
https://zh-hans.reactjs.org/docs/typechecking-with-proptypes.html
https://zhuanlan.zhihu.com/p/35344200
https://blog.csdn.net/weixin_45271385/article/details/103038902