這一章節討論元件屬性(亦稱為props)。
元件屬性是什麼?
元件屬性(props)的功能和 HTML attribute 類似。換句話說, props 為元件提供配置值。例如,下面程式碼中的 Badge 元件,當它被例項化時,它期望獲取一個名為 name 的屬性。
當 <BadgeList> 元件裡的 render 函式呼叫 <Badge> 元件時,name 屬性會被新增到 <Badge> 元件中,類似於 HTML 屬性被新增到 HTML 元素中 (比如, <Badge name=”Bill” />). 然後 name 屬性就可以被 Badge 元件使用了(比如,this.props.name). 這就像 <input> 元素用一個 value 屬性就可以展示這個 value 了一樣.
還有一種理解元件屬性的方法,即這些屬性都是元件的配置值。如果你看了之前 non-JSX 版本的程式碼示例,很明顯的,元件屬性只是一個物件,作為引數傳送給 createElement() 函式(比如,React.createElement(Badge, { name: “Bill” }).
var Badge = React.createClass({
displayName: "Badge",
render: function render() {
return React.createElement(
"div",
null, //no props defined, so null
this.props.name //use passed this.prop.name as text node
);
}
});
var BadgeList = React.createClass({
displayName: "BadgeList",
render: function render() {
return React.createElement(
"div",
null,
React.createElement(Badge, { name: "Bill" }),
React.createElement(Badge, { name: "Tom" })
);
}
});
ReactDOM.render(React.createElement(BadgeList, null), document.getElementById(`app`));
這類似於 props 可以在 React 節點中被直接設定(參見 4.4 和 5.7)。當 createElement() 函式的引數為一個元件定義(比如,Badge),而不是一個節點時,元件屬性在該元件自身中也是可用的(比如,this.props.name)。
元件屬性讓重用帶有任何屬性名的 <Badge> 元件成為可能。
在之前的程式碼示例中,BadgeList 元件使用了兩個 Badge 元件,它們分別帶有自己的 this.props 物件 。當一個 Badge 元件被例項化時,我們可以通過控制檯輸出 this.props 值來確定它是哪一個。
基本上每個 React 元件例項都有一個獨特的例項屬性,該屬性稱為 props,一開始它是個空的 JavaScript 物件。這個空物件可以被父元件用 JavaScript 的 值/ 引數 填充。這些值被該元件使用或傳遞給子元件。
本節筆記
在 ES5 環境/引擎中,你不能改變 this.props ,因為它被凍結了(比如,Object.isFrozen(this.props) === true; );
this.props 是隻讀的。
傳送元件屬性
給元件新增屬性值時,必須是在元件被使用的時候,而不是在元件被定義的時候。比如,下面的程式碼中, Badge 元件首先被定義,然後再給它新增屬性。當該元件被使用的時候 name=“Bill” 才被新增上去(比如,<Badge name=”Bill” /> 被渲染的時候).
var Badge = React.createClass({
render: function() {
return <div>{this.props.name}</div>;
}
});
ReactDOM.render(<Badge name="Bill" />, document.getElementById(`app`));
元件在被呼叫的時候,不管在哪呼叫,都可以給它傳遞屬性。
var Badge = React.createClass({
render: function() {
return <div>{this.props.name}</div>;
}
});
var BadgeList = React.createClass({
render: function() {
return (<div>
<Badge name="Bill" />
<Badge name="Tom" />
</div>);
}
});
ReactDOM.render(<BadgeList />, document.getElementById(`app`));
本節筆記
元件屬性是不可變的,並且元件不能夠內部修改從它父級傳遞過來的屬性。如果你一定要改變元件屬性,那麼該元件就要被重新渲染;不要使用 this.props.[PROP] = [NEW PROP] 這種方式來更改 props.
獲取元件屬性
正如 6.4 章節討論的那樣,一個元件例項可以通過 this 關鍵字獲取任何屬性值。比如,在下面的程式碼中,Badge 通過 this 關鍵字從 render 配置項中獲取 props(比如,this.props.name) .
var Badge = React.createClass({
render: function() {
return <div>{this.props.name}</div>;
}
});
ReactDOM.render(<Badge name="Bill" />, document.getElementById(`app`));
如果你看過轉化後的 Javascript (比如,JSX to JS),就沒什麼難掌握的。
var Badge = React.createClass({
displayName: "Badge",
render: function render() {
return React.createElement(
"div",
null,
this.props.name
);
}
});
ReactDOM.render(React.createElement(Badge, { name: "Bill" }), document.getElementById(`app`));
在上面程式碼示例中,{ name: “Bill” } 物件連同 Badge 元件一起做為 createElement() 函式的引數。該元件可以從 props 那裡瞭解到它的例項屬性值被設定為 { name: “Bill” }.
本節筆記
this.props 是隻讀的,不要通過 this.props.PROP = ‘foo` 去設定 props。
設定預設元件屬性
元件在被定義的時候,可以通過配置 getDefaultProps 來設定預設屬性。 如下示例:
如果這個元件沒有其他的 prop 傳遞進來的話,this.props 就是預設屬性。你可以用上面的程式碼驗證下,即不帶 name 屬性的 Badge 元件例項使用的是預設屬性 `John Doe’。
本節筆記
元件被建立的時候,getDefaultProps 呼叫一次並被快取。
元件例項建立之前 getDefaultProps 就執行了,因此在 getDefaultProps 裡使用 this.props 是沒用的。
由 getDefaultProps() 返回的任何物件可以跨例項共享,但不能被複制。
元件屬性不僅僅是字串
確保要理解一個元件屬性可以是任何有效的 JavaScript 值。
如下示例:
注意當 MyComponent 被建立的時候, propArray 和 propObject 被新值覆蓋了。
這裡的要點就是當你傳遞屬性值的時候,不要僅侷限於傳遞字串。
驗證元件屬性
定義元件的時候,propTypes 的配置項可以用來驗證傳遞給 props 的屬性值是否符合要求。如下面程式碼示例所示:
如果我沒有按照 propTypes 中指定的屬性型別去傳送屬性,它就會導致錯誤。比如,上面的程式碼會在控制檯中顯示如下的錯誤:
Warning: Failed propType: Invalid prop `propArray` of type `object` supplied to `MyComponent`, expected `array`
Warning: Failed propType: Required prop `propFunc` was not specified in `MyComponent`.
Uncaught TypeError: this.props.propFunc is not a function
然而,下面正確的那個元件渲染永遠都不會導致錯誤:
ReactDOM.render(<MyComponent propArray={[1,2]} propFunc={function(){return 3;}} />, document.getElementById(`app`));
React 也提供了一些自帶的驗證處理(比如,React.PropTypes[VALIDATOR])(也可以建立自定義驗證):
基本型別驗證
這些驗證檢查 prop 是否是一個特殊的 JS 原生值。這些預設都是可選的。也就是說,只有設定了 prop,驗證才會進行。
連結
歡迎指正修改。