1.引言--JavaScript就是一个熊孩子

1.1对于JSer们来说,JS是自由的,但同时又有许多让人烦恼的地方.javascript 很多时候就是这么一个熊孩子,他很多时候并不会像Ç和java的这些“好孩子”那样循规蹈矩。因此给我们带来许多烦恼

<1>运行时候控制台报错:未记错误,尤其这令人恼火的的英文系统-告诉我们有错误但是又不告诉我们错误发生在哪里试想一下,你到一个地方旅游迷了路,一个当地的熊孩子一直笑嘻嘻地跟在你后头告诉你?!“你走错啦”但是不告诉你应该怎么走,你会不会很想揍他一顿(╬皿)

<2>运行时报了确定的错误,然而我们发现这TM完全是一条驴唇不对马嘴的错误报告。甚至于去计算器上寻找答案,却发现提问的错误场景跟自己的根本是两码事。让我们回到1中场景,假如这个熊孩子很好心地告诉了你路线,结果你走到天黑发现被熊孩子狠狠得耍了,导致你不得不在大晚上露宿街头,你会不会比1中场景更想揍他一顿?(╬皿¯)

<3>你主观地写错了了一个变量的类型,比如把字符串1写成数字1,但是系统“很好心”地不报错误提示。(我们都不需要特别的进行类型声明当然不会报告错误提示啦)而这却可能就是你接下来错误的源头让我们回到1,2中场景。假如这个熊孩子知道你这个外地人绝逼是走错路了,但当你问路:“我走对路了吗?”时候,他笑靥如花满面春风得点点头,让你充满信心充满希望得一条路走到黑。我想你此时的心情不会比1和2中的要好(╬皿¯)

<2>中情况有时候比较难以避免

<1>中情况我们可以通过熟悉主要的6种uncaught error的情形加以判断。(在下一篇文章里我会讨论这个问题)

<3>中的情况呢,完全可以用类型检测的方式加以避免,这也就是我这篇文章所讲到的内容

本节主要讨论的是与反应配套的类型检测库--prop类型的运用

今天我在这篇文章里面介绍的内容,就是通过反应过来的propTypes进行类型检测。顾名思义丙类型就是对反应组件中道具对象中的变量进行类型检测的,因为道具的英文反应数据流的管道,我们通过丙类型就可以轻松监控反应里大多数据的变量类型先介绍下propTypes的基本用法。

2.prop类型基础入门

2.1首先你需要通过在终端npm install prop-types安装一个叫prop-types的第三方包

2.2然后通过下面的写法对你的某一个组件的道具中的变量进行类型检测:

yourComponent.propTypes = {属性1:属性1的变量类型,属性2:属性2的变量类型//...
}

3.propTypes的使用全解

3.1利用propTypes检测全部数据类型的变量

import React from 'react'class Son extends React.Component{render(){return (<div style ={{padding:30}}>{this.props.number}<br/>{this.props.array}<br/>{this.props.boolean.toString()}</div>)}
}
class Father extends React.Component{render(){return (<Sonnumber = {'1'}array = {'[1,2,3]'}boolean = {'true'}/>)}
}

比如这个例子,我们通过道具从父组件向子组件传递属性,你原本试图通过数目,阵列和布尔这三个属性分别向子中传递一个数字,数组和一个布尔型数值,但由于你刚一下子追完了50多集“人民的名义”,导致你过度疲惫,把它们都写成了字符串,虽然渲染是正常的,但这可能会导致你接下来调用一些方法的时候发生错误,而系统并不提供任何提示。

让我们给它加上propTypes的类型检测:

import React from 'react'
import PropTypes from 'prop-types';
class Son extends React.Component{render(){return (<div style ={{padding:30}}>{this.props.number}<br/>{this.props.array}<br/>{this.props.boolean.toString()}</div>)}
}
Son.propTypes = {number:PropTypes.number,array:PropTypes.array,boolean:PropTypes.bool
}
class Father extends React.Component{render(){return (<Sonnumber = {'1'}array = {'[1,2,3]'}boolean = {'true'}/>)}
}

然后我们就能看到报的错误了,而且这个时候,报的错误包括错误的道具属性名称,错误的变量类型,属性所在的组件名称,预期的正确的变量类型,错误代码的位置以及其他更详细的信息。

这种“人为控制”的报错比一般的系统报错看起来应该要亲切自然得多吧...你大可以说:这个错误是我“私人定制”的呦(//▽//)

propTypes能用来检测全部数据类型的变量,包括基本类型的的字符串,布尔值,数字,以及引用类型的对象,数组,函数,甚至还有ES6新增的符号类型

Son.propTypes = {optionalArray: PropTypes.array,//检测数组类型optionalBool: PropTypes.bool,//检测布尔类型optionalFunc: PropTypes.func,//检测函数(Function类型)optionalNumber: PropTypes.number,//检测数字optionalObject: PropTypes.object,//检测对象optionalString: PropTypes.string,//检测字符串optionalSymbol: PropTypes.symbol,//ES6新增的symbol类型
}

【注意】下面这些是从官方英文文档里引用过来的,你大概能够注意到,五种基本类型中的不确定和空并不在此列,propTypes类型检测的缺憾之一是,对于不确定的和无效的值,它无法捕捉错误

让我们把上述实例中的父组件传递给子组件修改一下,改成:

class Father extends React.Component{render(){return (<Sonnumber = {null}array = {null}boolean = {null}/>)}
}

结果是输出台不报任何错误,(当然你改成未定义也是同样效果)。

3.2  通过oneOfType实现多选择检测-可规定多个检测通过的数据类型

上个例子中类型检测的要求是一个变量对应一个数据类型,也就是规定的变量类型只有一个。那么怎样能让它变得灵活一些,比如规定多个可选的数据类型都为检测通过呢? PropTypes里的oneOfType方法可以做到这一点,oneOfType方法接收参数的是一个数组,数组元素是你希望检测通过的数据类型。

import React from 'react'
import PropTypes from 'prop-types';
class Son extends React.Component{
render(){
return (<div style ={{padding:30}}>
{this.props.number}
</div>)
}
}
Son.propTypes = {
number:PropTypes.oneOfType(
[PropTypes.string,PropTypes.number]
)
}
class Father extends React.Component{
render(){
//分别渲染数字的11和字符串的11
return (<div>
<Son number = {'字符串11'}/>
<Son number = {11}/>
</div>)
}
}

这时候,因为在类型检测中,号码属性的规定类型包括字符串和数字两种,所以此时控制台无报错

当然,如果你改为number = {数组或其他类型的变量},那么这时就会报错了

3.3  通过oneOf实现多选择检测-可规定多个检测通过的变量的值

3.2是规定了多个可检测通过的数据类型,那么同样的道理,我们也可以规定多个可检测通过的变量的值,这就要用到PropTypes里的oneOf方法,和PropTypes方法一样oneOf方法接收参数的是一个数组,数组元素是你希望检测通过的变量的值,比如我们把上面类型检测的部分改成:

Son.propTypes = {number:PropTypes.oneOf([12,13])
}

那么运行时就会报这样一段错误:

3.4 arrayOf,objectOf实现多重嵌套检测

试想一下,如果我们检测的是基本类型的变量,那么这自然是很简单的,但当我们要检测的是一个引用类型的变量呢?当我们除了检测这个变量是否符合规定的引用类型外(对象/阵列),还想要进一步检测对象中的属性变量或阵列中数组元素的数据类型时,单靠上面的方法已经不能满足要求了。这时候就要用到PropTypes的arrayOf,objectOf方法。

arrayOf接收一个参数,这个参数是规定的数组元素的数据类型.objectOf接收的参数则是属性的数据类型

我们对上述例子做些修改:

import React from 'react'
import PropTypes from 'prop-types';
class Son extends React.Component{render(){return (<div style ={{padding:30}}>{this.props.array}</div>)}
}
Son.propTypes = {array:PropTypes.arrayOf(PropTypes.number)
}
class Father extends React.Component{render(){return (<div><Son array = {[1,2,3,4]}/></div>)
}
}

正常渲染,然后我们把<Son array = {[1,2,3,4]} />改为<Son array = {['1','2','3','4']} /> ,报错

【注意】虽然报错但是这并不会影响程序的正常运行(譬如上面我们看到渲染仍然是正常的),因为本质上说类型检测报的是非致命性错误的警告而不是致命性错误的错误(区别在于是否影响了正常运行)。对objectOf也是同样的做法

3.5  通过形状方法检测目标对象不同属性的不同数据类型

如果你认真思考一下的话,你会发现3.4中的objectOf有一个缺陷,就是它内部的属性的数据类型被强行规定为一种,但通常一个对象里应该是有多种不同类型的属性了,那么这时候objectOf就不符合要求了,我们应该使用形状方法,其用法:

PropTypes.shape({属性1:类型1,属性2:类型2,//...
}),

举个例子:

import React from 'react'
import PropTypes from 'prop-types';
class Son extends React.Component{render(){return (<div style ={{padding:30}}>{'我的名字叫' + this.props.object.name}<br/>{'我的年龄是' + this.props.object.age}</div>)}
}
Son.propTypes = {object:PropTypes.shape({name:PropTypes.string,age:PropTypes.number})
}
class Father extends React.Component{render(){return (<div><Son object = {{name:'彭湖湾',age:20}}/></div>)}
}

无报错,把<Son object = {{name:'彭湖湾',年龄:20}} />改成<Son object = {{name:'彭湖湾',年龄:'20'}} /> ,然后就能喜闻乐见得报错了

3.6通过isRequired检测道具中某个必要的属性(如果该属性不存在就报错)

有时候,我们在对某个变量进行类型检测时,我们不仅要求它符合预期的类型,同时也要求它是必须写入的,这时候就要用到isRequired。

【分析】

Son.propTypes = {number:PropTypes.number
}

这段代码的作用是当你在道具中写入号码属性且号码属性类型错误时给予报错提示,可如果你压根就没有写入号码属性呢?没错,什么错误都不会报。这就是使用isRequired的必要性

【栗子】

import React from 'react'
import PropTypes from 'prop-types';
class Son extends React.Component{render(){return (<div style ={{padding:30}}>{this.props.number}</div>)}
}
Son.propTypes = {number:PropTypes.number
}
class Father extends React.Component{render(){return (<div><Son /></div>)}
}

控制台无任何输出

如果我们改成:

Son.propTypes = {number:PropTypes.number.isRequired
}

再运行,我们就又可以喜闻乐见得看到错误了:

【注意】在这里给大家提个问题:我们上述的写法是数量:PropTypes.number.isRequired,这要求数是数字类型,但如果你不想控制数的类型而仅仅是想控制它的必要性呢?难道写成号:isRequired或number:PropTypes.isRequired? 这个时候PropTypes.any就登场啦!它代表了该变量可取任何一种数据类型,所以你可以写成这样--number:PropTypes.any.isRequired

3.7应对更复杂的类型检测 - 将PropTypes的属性值写成函数

Son.propTypes = {prop:function(props,propName,componentName){if(/*判断条件*/){return new Error(/*错误的参数*/)}}
}

在属性prop的类型检测中,属性值是一个函数,在这里props是包含prop的props对象,propName是prop的属性名,componentName是props所在的组件名称,函数的返回值是一个Error对象

import React from 'react'
import PropTypes from 'prop-types';
class Son extends React.Component{render(){return (<div style ={{padding:30}}>{this.props.email}</div>)}
}
Son.propTypes = {email:function(props,propName,componentName){if(!/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/.test(props[propName])){return new Error('组件' + componentName+ '里的属性' + propName + '不符合邮箱的格式');}}
}
class Father extends React.Component{render(){return (<div><Son email = {2314838004}/></div>)}
}

在这里我们利用正则表达式检测传递到Son组件的email属性是否符合邮箱格式,如果不符合就抛出错误,那么2314838004显然不符合这一要求,所以我们就得到下面的demo:(其实加上qq.com就是我的邮箱啦 哈哈)

4.ES7下类型检测的新写法:

可能你觉得把propTypes写在类外看起来有些怪怪的,在ES7的静态类属性的支持下,你可以这样写:

class Son extends React.Component{
static propTypes = {//..类型检测
}
render(){return (/* 渲染*/)}
}

但注意,这在ES7下生效

5.props-types的独立与react.PropTypes的弃用

在上面我是利用props-types这个独立的第三方库来进行类型检测的,但在不久前(react V15.5以前),它使用的是react内置的类型检测,而不是第三方库(也就是说我们现在的prop-types是当初以react内置的PropTypes对象为基础分离出来的)

翻译成中文就是:

所以说在你也可以这样进行类型检测,虽然并不推荐(为了保持向下兼容这在最新版本的react上仍然是可用的)

Son.propTypes = {number:React.PropTypes.number
}

6.参考资料:

react官方文档/高级指导/类型检测(docs/advanced guide/Typechecking with propTypes)

https://facebook.github.io/react/docs/typechecking-with-proptypes.html

转载地址:https://www.cnblogs.com/penghuwan/p/6796139.html

react prop-types的使用讲解相关推荐

  1. React Native集成Redux框架讲解与应用

    学过React Native的都知道,RN的UI是根据相应组件的state进行render的,而页面又是由大大小小的组件构成,导致每个组件都必须维护自身的一套状态,因此当页面复杂化的时候,管理stat ...

  2. 基础篇章:React Native之 ScrollView 的讲解

    大家好,我是ScrollView,相信做过移动或者前端开发的人肯定都很熟悉我,对,我就是那个可以滚动的容器,滚有点难听,我是可以滑动的容器,我滑动起来,摩擦摩擦,似魔鬼的步伐.我不仅可以上下滚动,就是 ...

  3. 基础篇章:React Native之 Image 的讲解

    今天一起来学习一些Image这个组件,它其实就是相当于我们android控件中的ImageView. 我们先看例子,看看加载本地图片和远程服务器图片的方式,其实差不多. import React, { ...

  4. [Recompose] Pass a React Prop to a Stream in RxJS

    When you declare your Component and Props in JSX, you can pass those props along to your RxJS stream ...

  5. 从零开始的 React 组件开发之路 (一):表格篇

    React 下的表格狂想曲 0. 前言 欢迎大家阅读「从零开始的 React 组件开发之路」系列第一篇,表格篇.本系列的特色是从 需求分析.API 设计和代码设计 三个递进的过程中,由简到繁地开发一个 ...

  6. 如何使用Webpack 4简化React.js开发过程

    by Margarita Obraztsova 玛格丽塔(Margarita Obraztsova) 如何使用Webpack 4简化React.js开发过程 (How to streamline yo ...

  7. 我如何使用React和Typescript在freeCodeCamp中构建天气应用

    by Kelvin Mai 通过凯文麦 我如何使用React和Typescript在freeCodeCamp中构建天气应用 (How I built the weather app in freeCo ...

  8. 把这304道React的面试题刷完,前端面试没有在怕的!

    Core React 什么是 React? React 是一个开源前端 JavaScript 库,用于构建用户界面,尤其是单页应用程序.它用于处理网页和移动应用程序的视图层.React 是由 Face ...

  9. React 面试题 回答

    原文https://github.com/semlinker/reactjs-interview-questions 本项目的面试题来源于 sudheerj/reactjs-interview-que ...

  10. react.js app_在React.JS中创建一个Weather App

    react.js app Hello readers! 各位读者好! In this article, you will know how to develop a basic weather app ...

最新文章

  1. Python中的map()函数
  2. django手机访问_在手机上运行Python的神器
  3. faster rcnn源码解读总结
  4. POPUP_TO_DECIDE
  5. linux反调试代码,linux反调试方法
  6. OpenCV C++ 06 - Histogram Equalization of a Grayscale image with OpenCV
  7. .Net Core实战之基于角色的访问控制的设计
  8. 麒麟810处理器_麒麟810性能实测:对比骁龙845骁龙730,谁更强?
  9. mysql 逗号金额比较,如何使用MySQL比较两个逗号分隔的字符串列表
  10. SVG 教程 (一)
  11. 手游项目初期的一些想法
  12. 利用计算机的图形能力来进行设计工作的是,计算机一级MSOffice考试巩固练习题...
  13. 【数据库原理实验(openGauss)】数据库的备份与恢复
  14. smarty3.X新命名规范引起的'Call of unknown method'
  15. 【工具向】分析FGUI依赖关系工具
  16. vi编辑器的使用   快捷键
  17. 高精度电压基准电路-TL431实现
  18. 手机qlv转mp4工具
  19. HDU 1863 (图论基础prim算法)
  20. VirtualBox安装Ubuntu20.04 + 安装增强功能

热门文章

  1. java计算机毕业设计课程在线反馈系统源程序+mysql+系统+lw文档+远程调试
  2. 小程序电子签名,解决安卓保存图片是黑色背景的问题
  3. 解决蓝牙和WiFi冲突问题
  4. 如何优雅的判断一个数字在一个范围内
  5. 〖百宝书-思维锻炼③〗——三心理论——成功的来源
  6. Qt 集成miniblink浏览器库之5 支持独立窗口和子窗口
  7. InsertOrUpdate的一些注意项
  8. linemod算法过程理解
  9. crx文件安装Chrome插件提示程序包无效的解决办法
  10. 7-21 超速判断 (10分)