組件是相互獨立、可複用的單元,一個組件可能在不一樣地方被用到。可是在不一樣的場景下對這個組件的需求可能會根據狀況有所不一樣,例如一個點贊按鈕組件,在我這裏須要它顯示的文本是「點贊」和「取消」,當別的同事拿過去用的時候,卻須要它顯示「贊」和「已贊」。如何讓組件能適應不一樣場景下的需求,咱們就要讓組件具備必定的「可配置」性。html
React.js 的 props
就能夠幫助咱們達到這個效果。每一個組件均可以接受一個 props
參數,它是一個對象,包含了全部你對這個組件的配置。就拿咱們點贊按鈕作例子:數組
下面的代碼可讓它達到上述的可配置性:函數
class LikeButton extends Component { constructor () { super() this.state = { isLiked: false } } handleClickOnLikeButton () { this.setState({ isLiked: !this.state.isLiked }) } render () { const likedText = this.props.likedText || '取消' const unlikedText = this.props.unlikedText || '點贊' return ( <button onClick={this.handleClickOnLikeButton.bind(this)}> {this.state.isLiked ? likedText : unlikedText} 👍 </button> ) } }
從 render
函數能夠看出來,組件內部是經過 this.props
的方式獲取到組件的參數的,若是 this.props
裏面有須要的屬性咱們就採用相應的屬性,沒有的話就用默認的屬性。this
那麼怎麼把 props
傳進去呢?在使用一個組件的時候,能夠把參數放在標籤的屬性當中,全部的屬性都會做爲 props
對象的鍵值:spa
class Index extends Component { render () { return ( <div> <LikeButton likedText='已贊' unlikedText='贊' /> </div> ) } }
就像你在用普通的 HTML 標籤的屬性同樣,能夠把參數放在表示組件的標籤上,組件內部就能夠經過 this.props
來訪問到這些配置參數了。code
前面的章節咱們說過,JSX 的表達式插入能夠在標籤屬性上使用。因此其實能夠把任何類型的數據做爲組件的參數,包括字符串、數字、對象、數組、甚至是函數等等。例如如今咱們把一個對象傳給點贊組件做爲參數:htm
class Index extends Component { render () { return ( <div> <LikeButton wordings={{likedText: '已贊', unlikedText: '贊'}} /> </div> ) } }
如今咱們把 likedText
和 unlikedText
這兩個參數封裝到一個叫 wordings
的對象參數內,而後傳入點贊組件中。你們看到 {{likedText: '已贊', unlikedText: '贊'}}
這樣的代碼的時候,不要覺得是什麼新語法。以前討論過,JSX 的 {}
內能夠嵌入任何表達式,{{}}
就是在 {}
內部用對象字面量返回一個對象而已。對象
這時候,點贊按鈕的內部就要用 this.props.wordings
來獲取到到參數了:blog
class LikeButton extends Component { constructor () { super() this.state = { isLiked: false } } handleClickOnLikeButton () { this.setState({ isLiked: !this.state.isLiked }) } render () { const wordings = this.props.wordings || { likedText: '取消', unlikedText: '點贊' } return ( <button onClick={this.handleClickOnLikeButton.bind(this)}> {this.state.isLiked ? wordings.likedText : wordings.unlikedText} 👍 </button> ) } }
甚至能夠往組件內部傳入函數做爲參數:字符串
class Index extends Component { render () { return ( <div> <LikeButton wordings={{likedText: '已贊', unlikedText: '贊'}} onClick={() => console.log('Click on like button!')}/> </div> ) } }
這樣能夠經過 this.props.onClick
獲取到這個傳進去的函數,修改 LikeButton
的 handleClickOnLikeButton
方法:
... handleClickOnLikeButton () { this.setState({ isLiked: !this.state.isLiked }) if (this.props.onClick) { this.props.onClick() } } ...
當每次點擊按鈕的時候,控制檯會顯示 Click on like button!
。但這個行爲不是點贊組件本身實現的,而是咱們傳進去的。因此,一個組件的行爲、顯示形態均可以用 props
來控制,就能夠達到很好的可配置性。
上面的組件默認配置咱們是經過 ||
操做符來實現。這種須要默認配置的狀況在 React.js 中很是常見,因此 React.js 也提供了一種方式 defaultProps
,能夠方便的作到默認配置。
class LikeButton extends Component { static defaultProps = { likedText: '取消', unlikedText: '點贊' } constructor () { super() this.state = { isLiked: false } } handleClickOnLikeButton () { this.setState({ isLiked: !this.state.isLiked }) } render () { return ( <button onClick={this.handleClickOnLikeButton.bind(this)}> {this.state.isLiked ? this.props.likedText : this.props.unlikedText} 👍 </button> ) } }
注意,咱們給點贊組件加上了如下的代碼:
static defaultProps = { likedText: '取消', unlikedText: '點贊' }
defaultProps
做爲點贊按鈕組件的類屬性,裏面是對 props
中各個屬性的默認配置。這樣咱們就不須要判斷配置屬性是否傳進來了:若是沒有傳進來,會直接使用 defaultProps
中的默認屬性。 因此能夠看到,在 render
函數中,咱們會直接使用 this.props
而不須要再作判斷。
props
一旦傳入進來就不能改變。修改上面的例子中的 handleClickOnLikeButton
:
... handleClickOnLikeButton () { this.props.likedText = '取消' this.setState({ isLiked: !this.state.isLiked }) } ...
咱們嘗試在用戶點擊按鈕的時候改變 this.props.likedText
,而後你會看到控制檯報錯了:
你不能改變一個組件被渲染的時候傳進來的 props
。React.js 但願一個組件在輸入肯定的 props
的時候,可以輸出肯定的 UI 顯示形態。若是 props
渲染過程當中能夠被修改,那麼就會致使這個組件顯示形態和行爲變得不可預測,這樣會可能會給組件使用者帶來困惑。
但這並不意味着由 props
決定的顯示形態不能被修改。組件的使用者能夠主動地經過從新渲染的方式把新的 props
傳入組件當中,這樣這個組件中由 props
決定的顯示形態也會獲得相應的改變。
修改上面的例子的 Index
組件:
class Index extends Component { constructor () { super() this.state = { likedText: '已贊', unlikedText: '贊' } } handleClickOnChange () { this.setState({ likedText: '取消', unlikedText: '點贊' }) } render () { return ( <div> <LikeButton likedText={this.state.likedText} unlikedText={this.state.unlikedText} /> <div> <button onClick={this.handleClickOnChange.bind(this)}> 修改 wordings </button> </div> </div> ) } }
在這裏,咱們把 Index
的 state
中的 likedText
和 unlikedText
傳給 LikeButton
。Index
還有另一個按鈕,點擊這個按鈕會經過 setState
修改 Index
的 state
中的兩個屬性。
因爲 setState
會致使 Index
從新渲染,因此 LikedButton
會接收到新的 props
,而且從新渲染,因而它的顯示形態也會獲得更新。這就是經過從新渲染的方式來傳入新的 props
從而達到修改 LikedButton
顯示形態的效果。
this.props
獲取到配置參數,組件能夠根據 props
的不一樣來肯定本身的顯示形態,達到可配置的效果。defaultProps
來配置默認參數。props
一旦傳入,你就不能夠在組件內部對它進行修改。可是你能夠經過父組件主動從新渲染的方式來傳入新的 props
,從而達到更新的效果。