溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

利用prop-types第三方庫(kù)對(duì)組件的props中的變量進(jìn)行類(lèi)型檢測(cè)

發(fā)布時(shí)間:2020-10-12 20:44:40 來(lái)源:腳本之家 閱讀:208 作者:外婆的彭湖灣 欄目:web開(kāi)發(fā)

1.引言——JavaScript就是一個(gè)熊孩子

1.1對(duì)于JSer們來(lái)說(shuō),js是自由的,但同時(shí)又有許多讓人煩惱的地方。javascript很多時(shí)候就是這么一個(gè)熊孩子,他很多時(shí)候并不會(huì)像C和java這些“好孩子”那樣循規(guī)蹈矩。因此給我們帶來(lái)許多煩惱

<1>運(yùn)行時(shí)候控制臺(tái)報(bào)錯(cuò):uncaught error,這尤其令人惱火的是系統(tǒng)告訴我們有錯(cuò)誤但是又不告訴我們錯(cuò)誤發(fā)生在哪里。試想一下,你到一個(gè)地方旅游迷了路,一個(gè)當(dāng)?shù)氐男芎⒆右恢毙ξ馗谀愫箢^告訴你:“你走錯(cuò)啦!”。但是不告訴你應(yīng)該怎么走,你會(huì)不會(huì)很想揍他一頓?(╬ ̄皿 ̄)

<2>運(yùn)行時(shí)報(bào)了確定的錯(cuò)誤,然而我們發(fā)現(xiàn)這TM完全是一條驢唇不對(duì)馬嘴的錯(cuò)誤報(bào)告。甚至于去stackoverflow上尋找答案,卻發(fā)現(xiàn)提問(wèn)的錯(cuò)誤場(chǎng)景跟自己的根本是兩碼事。讓我們回到1中場(chǎng)景,假如這個(gè)熊孩子很好心地告訴了你路線,結(jié)果你走到天黑發(fā)現(xiàn)被熊孩子狠狠得耍了,導(dǎo)致你不得不在大晚上露宿街頭,你會(huì)不會(huì)比1中場(chǎng)景更想揍他一頓?(╬ ̄皿 ̄) 

<3>你主觀地寫(xiě)錯(cuò)了了一個(gè)變量的類(lèi)型,比如把字符串1寫(xiě)成數(shù)字1,但是系統(tǒng)“很好心”地不報(bào)錯(cuò)誤提示。(我們都不需要特別的進(jìn)行類(lèi)型聲明當(dāng)然不會(huì)報(bào)告錯(cuò)誤提示啦)而這卻可能就是你接下來(lái)bug的源頭。讓我們回到1,2中場(chǎng)景,假如這個(gè)熊孩子知道你這個(gè)外地人絕逼是走錯(cuò)路了,但當(dāng)你問(wèn)路:“我走對(duì)路了嗎?”時(shí)候,他笑靨如花滿面春風(fēng)得點(diǎn)點(diǎn)頭,讓你充滿信心充滿希望得一條路走到黑。我想你此時(shí)的心情不會(huì)比1和2中的要好(╬ ̄皿 ̄)

<2>中情況有時(shí)候比較難以避免

<1>中情況我們可以通過(guò)熟悉主要的6種uncaught error的情形加以判斷。(在下一篇文章里我會(huì)討論這個(gè)問(wèn)題)

<3>中的情況呢,完全可以用類(lèi)型檢測(cè)的方式加以避免,這也就是我這篇文章所講到的內(nèi)容

本節(jié)主要討論的是與react配套的類(lèi)型檢測(cè)庫(kù)——prop-types的運(yùn)用

今天我在這篇文章里面介紹的內(nèi)容,就是通過(guò)react的propTypes進(jìn)行類(lèi)型檢測(cè),。顧名思義prop-types就是對(duì)react組件中props對(duì)象中的變量進(jìn)行類(lèi)型檢測(cè)的,因?yàn)閜rops是react數(shù)據(jù)流的管道,我們通過(guò)prop-types就可以輕松監(jiān)控react里大多數(shù)據(jù)的變量類(lèi)型先介紹下propTypes的基本用法。

2.prop-types基礎(chǔ)入門(mén)

2.1首先你需要通過(guò)在終端npm install prop-types安裝一個(gè)叫prop-types的第三方包

2.2然后通過(guò)下面的寫(xiě)法對(duì)你的某一個(gè)組件的props中的變量進(jìn)行類(lèi)型檢測(cè):

yourComponent.propTypes = {
  屬性1:屬性1的變量類(lèi)型,
  屬性2:屬性2的變量類(lèi)型
  //...
} 

3.propTypes的使用全解

3.1利用propTypes檢測(cè)全部數(shù)據(jù)類(lèi)型的變量

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 (<Son
    number = {'1'}
    array = {'[1,2,3]'}
    boolean = {'true'}
    />)
   }
}

比如這個(gè)例子,我們通過(guò)props從父組件向子組件傳遞屬性,你原本試圖通過(guò)number,array和boolean這三個(gè)屬性分別向Son中傳遞一個(gè)數(shù)字,數(shù)組和一個(gè)布爾型數(shù)值,但由于你過(guò)度疲憊,把它們都寫(xiě)成了字符串,雖然渲染是正常的,但這可能會(huì)導(dǎo)致你接下來(lái)調(diào)用一些方法的時(shí)候發(fā)生錯(cuò)誤,而系統(tǒng)并不提供任何提示。

利用prop-types第三方庫(kù)對(duì)組件的props中的變量進(jìn)行類(lèi)型檢測(cè)

利用prop-types第三方庫(kù)對(duì)組件的props中的變量進(jìn)行類(lèi)型檢測(cè)

讓我們給它加上propTypes的類(lèi)型檢測(cè):

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 (<Son
      number = {'1'}
      array = {'[1,2,3]'}
      boolean = {'true'}
      />)
     }
}

然后我們就能看到報(bào)的錯(cuò)誤了,而且這個(gè)時(shí)候,報(bào)的錯(cuò)誤包括錯(cuò)誤的props屬性名稱(chēng),錯(cuò)誤的變量類(lèi)型,屬性所在的組件名稱(chēng),預(yù)期的正確的變量類(lèi)型,錯(cuò)誤代碼的位置以及其他更詳細(xì)的信息。

這種“人為控制”的報(bào)錯(cuò)比一般的系統(tǒng)報(bào)錯(cuò)看起來(lái)應(yīng)該要親切自然得多吧...你大可以說(shuō):這個(gè)error是我“私人定制”的呦 (//▽//)

利用prop-types第三方庫(kù)對(duì)組件的props中的變量進(jìn)行類(lèi)型檢測(cè)

propTypes 能用來(lái)檢測(cè)全部數(shù)據(jù)類(lèi)型的變量,包括基本類(lèi)型的的string,boolean,number,以及引用類(lèi)型的object,array,function,甚至還有ES6新增的symbol類(lèi)型

Son.propTypes = {
  optionalArray: PropTypes.array,//檢測(cè)數(shù)組類(lèi)型
  optionalBool: PropTypes.bool,//檢測(cè)布爾類(lèi)型
  optionalFunc: PropTypes.func,//檢測(cè)函數(shù)(Function類(lèi)型)
  optionalNumber: PropTypes.number,//檢測(cè)數(shù)字
  optionalObject: PropTypes.object,//檢測(cè)對(duì)象
  optionalString: PropTypes.string,//檢測(cè)字符串
  optionalSymbol: PropTypes.symbol,//ES6新增的symbol類(lèi)型
}

【注意】下面這些是從官方英文文檔里引用過(guò)來(lái)的,你大概能夠注意到,五種基本類(lèi)型中的undefined和null并不在此列,propTypes類(lèi)型檢測(cè)的缺憾之一是,對(duì)于undefined和null的值,它無(wú)法捕捉錯(cuò)誤

讓我們把上述實(shí)例中的Father組件傳遞給Son組件修改一下,改成:

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

結(jié)果是輸出臺(tái)不報(bào)任何錯(cuò)誤,(當(dāng)然你改成undefined也是同樣效果)。 

利用prop-types第三方庫(kù)對(duì)組件的props中的變量進(jìn)行類(lèi)型檢測(cè)

3.2 通過(guò)oneOfType實(shí)現(xiàn)多選擇檢測(cè)——可規(guī)定多個(gè)檢測(cè)通過(guò)的數(shù)據(jù)類(lèi)型

上個(gè)例子中類(lèi)型檢測(cè)的要求是一個(gè)變量對(duì)應(yīng)一個(gè)數(shù)據(jù)類(lèi)型,也就是規(guī)定的變量類(lèi)型只有一個(gè)。那么怎樣能讓它變得靈活一些,比如規(guī)定多個(gè)可選的數(shù)據(jù)類(lèi)型都為檢測(cè)通過(guò)呢?PropTypes里的oneOfType方法可以做到這一點(diǎn),oneOfType方法接收參數(shù)的是一個(gè)數(shù)組,數(shù)組元素是你希望檢測(cè)通過(guò)的數(shù)據(jù)類(lèi)型。

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(){
   //分別渲染數(shù)字的11和字符串的11
  return (<div>
      <Son number = {'字符串11'}/>
      <Son number = {11}/>
     </div>)
    }
}

這時(shí)候,因?yàn)樵陬?lèi)型檢測(cè)中,number屬性的規(guī)定類(lèi)型包括字符串和數(shù)字兩種,所以此時(shí)控制臺(tái)無(wú)報(bào)錯(cuò)

利用prop-types第三方庫(kù)對(duì)組件的props中的變量進(jìn)行類(lèi)型檢測(cè)

當(dāng)然,如果你改為number = {數(shù)組或其他類(lèi)型的變量},那么這時(shí)就會(huì)報(bào)錯(cuò)了

利用prop-types第三方庫(kù)對(duì)組件的props中的變量進(jìn)行類(lèi)型檢測(cè)

3.3 通過(guò)oneOf實(shí)現(xiàn)多選擇檢測(cè)——可規(guī)定多個(gè)檢測(cè)通過(guò)的變量的值

3.2是規(guī)定了多個(gè)可檢測(cè)通過(guò)的數(shù)據(jù)類(lèi)型,那么同樣的道理,我們也可以規(guī)定多個(gè)可檢測(cè)通過(guò)的變量的值,這就要用到PropTypes里的oneOf方法,和PropTypes方法一樣oneOf方法接收參數(shù)的是一個(gè)數(shù)組,數(shù)組元素是你希望檢測(cè)通過(guò)的變量的值,比如我們把上面類(lèi)型檢測(cè)的部分改成:

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

那么運(yùn)行時(shí)就會(huì)報(bào)這樣一段錯(cuò)誤:

利用prop-types第三方庫(kù)對(duì)組件的props中的變量進(jìn)行類(lèi)型檢測(cè)

3.4 arrayOf,objectOf實(shí)現(xiàn)多重嵌套檢測(cè)

試想一下,如果我們檢測(cè)的是基本類(lèi)型的變量,那么這自然是很簡(jiǎn)單的,但當(dāng)我們要檢測(cè)的是一個(gè)引用類(lèi)型的變量呢?當(dāng)我們除了檢測(cè)這個(gè)變量是否符合規(guī)定的引用類(lèi)型外(Object/array),還想要進(jìn)一步檢測(cè)object中的屬性變量或array中數(shù)組元素的數(shù)據(jù)類(lèi)型時(shí),單靠上面的方法已經(jīng)不能滿足要求了。這時(shí)候就要用到PropTypes的arrayOf,objectOf方法。

arrayOf接收一個(gè)參數(shù),這個(gè)參數(shù)是規(guī)定的數(shù)組元素的數(shù)據(jù)類(lèi)型。objectOf接收的參數(shù)則是屬性的數(shù)據(jù)類(lèi)型

我們對(duì)上述例子做些修改:

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']}/>,報(bào)錯(cuò)

利用prop-types第三方庫(kù)對(duì)組件的props中的變量進(jìn)行類(lèi)型檢測(cè)

【注意】雖然報(bào)錯(cuò)但是這并不會(huì)影響程序的正常運(yùn)行(譬如上面我們看到渲染仍然是正常的),因?yàn)楸举|(zhì)上說(shuō)類(lèi)型檢測(cè)報(bào)的是非致命性錯(cuò)誤warning而不是致命性錯(cuò)誤error(區(qū)別在于是否影響了正常運(yùn)行)。對(duì)objectOf也是同樣的做法

3.5 通過(guò)shape方法檢測(cè)目標(biāo)對(duì)象不同屬性的不同數(shù)據(jù)類(lèi)型

如果你認(rèn)真思考一下的話,你會(huì)發(fā)現(xiàn)3.4中的objectOf有一個(gè)缺陷,就是它內(nèi)部的屬性的數(shù)據(jù)類(lèi)型被強(qiáng)行規(guī)定為一種,但通常一個(gè)對(duì)象里應(yīng)該是有多種不同類(lèi)型的屬性了,那么這時(shí)候objectOf就不符合要求了,我們應(yīng)該使用shape方法,其用法:

PropTypes.shape({
 屬性1:類(lèi)型1,
 屬性2:類(lèi)型2,
 //...
}),

舉個(gè)例子:

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>)
  }
}

無(wú)報(bào)錯(cuò),把<Son object = {{name:'彭湖灣',age:20}}/>改成<Son object = {{name:'彭湖灣',age:'20'}}/>,然后就能喜聞樂(lè)見(jiàn)得報(bào)錯(cuò)了

利用prop-types第三方庫(kù)對(duì)組件的props中的變量進(jìn)行類(lèi)型檢測(cè)

3.6 通過(guò)isRequired檢測(cè)props中某個(gè)必要的屬性(如果該屬性不存在就報(bào)錯(cuò))

有時(shí)候,我們?cè)趯?duì)某個(gè)變量進(jìn)行類(lèi)型檢測(cè)時(shí),我們不僅要求它符合預(yù)期的類(lèi)型,同時(shí)也要求它是必須寫(xiě)入的,這時(shí)候就要用到isRequired。

【分析】

Son.propTypes = {
   number:PropTypes.number
}

這段代碼的作用是當(dāng)你在props中寫(xiě)入number屬性且number屬性類(lèi)型錯(cuò)誤時(shí)給予報(bào)錯(cuò)提示,可如果你壓根就沒(méi)有寫(xiě)入number屬性呢?沒(méi)錯(cuò),什么錯(cuò)誤都不會(huì)報(bào)。這就是使用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>)
  }
}

控制臺(tái)無(wú)任何輸出

利用prop-types第三方庫(kù)對(duì)組件的props中的變量進(jìn)行類(lèi)型檢測(cè)

如果我們改成:

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

再運(yùn)行,我們就又可以喜聞樂(lè)見(jiàn)得看到錯(cuò)誤了:

利用prop-types第三方庫(kù)對(duì)組件的props中的變量進(jìn)行類(lèi)型檢測(cè)

【注意】在這里給大家提個(gè)問(wèn)題:我們上述的寫(xiě)法是number:PropTypes.number.isRequired,這要求number是數(shù)字類(lèi)型,但如果你不想控制number的類(lèi)型而僅僅是想控制它的必要性呢?難道寫(xiě)成number:isRequired或number:PropTypes.isRequired? 這個(gè)時(shí)候PropTypes.any就登場(chǎng)啦!它代表了該變量可取任何一種數(shù)據(jù)類(lèi)型,所以你可以寫(xiě)成這樣——number: PropTypes.any.isRequired

3.7 應(yīng)對(duì)更復(fù)雜的類(lèi)型檢測(cè)——將PropTypes的屬性值寫(xiě)成函數(shù)

Son.propTypes = {
  prop:function(props,propName,componentName){
   if(/*判斷條件*/){
    return new Error(/*錯(cuò)誤的參數(shù)*/)
   }
 }
}

在屬性prop的類(lèi)型檢測(cè)中,屬性值是一個(gè)函數(shù),在這里props是包含prop的props對(duì)象,propName是prop的屬性名,componentName是props所在的組件名稱(chēng),函數(shù)的返回值是一個(gè)Error對(duì)象

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>)
    }
}

在這里我們利用正則表達(dá)式檢測(cè)傳遞到Son組件的email屬性是否符合郵箱格式,如果不符合就拋出錯(cuò)誤,那么2314838004顯然不符合這一要求,所以我們就得到下面的demo:(其實(shí)加上qq.com就是我的郵箱啦 哈哈)

利用prop-types第三方庫(kù)對(duì)組件的props中的變量進(jìn)行類(lèi)型檢測(cè)

4.ES7下類(lèi)型檢測(cè)的新寫(xiě)法:

可能你覺(jué)得把propTypes寫(xiě)在類(lèi)外看起來(lái)有些怪怪的,在ES7的靜態(tài)類(lèi)屬性的支持下,你可以這樣寫(xiě):

class Son extends React.Component{
static propTypes = {
  //..類(lèi)型檢測(cè)
}
render(){
 return (/* 渲染*/)
  }
}

但注意,這在ES7下生效

5.props-types的獨(dú)立與react.PropTypes的棄用

在上面我是利用props-types這個(gè)獨(dú)立的第三方庫(kù)來(lái)進(jìn)行類(lèi)型檢測(cè)的,但在不久前(react V15.5以前),它使用的是react內(nèi)置的類(lèi)型檢測(cè),而不是第三方庫(kù)(也就是說(shuō)我們現(xiàn)在的prop-types是當(dāng)初以react內(nèi)置的PropTypes對(duì)象為基礎(chǔ)分離出來(lái)的)

利用prop-types第三方庫(kù)對(duì)組件的props中的變量進(jìn)行類(lèi)型檢測(cè)

翻譯成中文就是:

利用prop-types第三方庫(kù)對(duì)組件的props中的變量進(jìn)行類(lèi)型檢測(cè)

所以說(shuō)在你也可以這樣進(jìn)行類(lèi)型檢測(cè),雖然并不推薦(為了保持向下兼容這在最新版本的react上仍然是可用的)

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

6.參考資料:

react官方文檔/高級(jí)指導(dǎo)/類(lèi)型檢測(cè)(docs/advanced guide/Typechecking with propTypes)

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

以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持億速云!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI