歡迎各位指導與討論 : )
前言
由於筆者英語和技術水平有限,有不足的地方懇請各位指出。我會及時修正的 O(∩_∩)O 當前React版本 15.0.1 時間 2016/4/25
正文
React一個最大的優點是,我們非常容易跟蹤React組件之間的數據流動。當我們觀察一個組件的時候,我們能夠容易、清晰地得知哪一些props正被傳輸。基於這一點,也使我們的代碼易懂。但是也有一種情況,當我們想在組件樹內部傳遞props,並且不想讓props流經樹的每一層,Context會讓我們做到這一點。
注:Context是一個先進易變的特性,它的API很可能會在未來的版本里改動。
當然,絕大多數應用無需使用到Context。因為使用Context會我們的代碼變得難懂,耦合度增強,復用性降低,同時也讓組件間的數據流動變得不夠清晰。Context就像我們在應用中使用全局變量一樣。我們應當謹慎使用Context。下面是一個例子
var Button = React.createClass({ contextTypes: { color: React.PropTypes.string }, render: function() { return ( <button style={{background: this.context.color}}> {this.props.children} </button>
); } }); var Message = React.createClass({ render: function() { return ( <div> {this.props.text} <Button>Delete</Button>
</div>
); } }); var MessageList = React.createClass({ childContextTypes: { color: React.PropTypes.string }, getChildContext: function() { return {color: "purple"}; }, render: function() { var children = this.props.messages.map(function(message) { return <Message text={message.text} />;
}); return <div>{children}</div>;
} });
在這個例子中,通過向MessageList(context provider)增加 childContextTypes 和 getChildContext,React 能夠自動地把信息(數據)向所有設置了 contextTypes 的子樹進行傳遞。如果 contextTypes 在子組件中還沒有定義,那 this.context將會是一個空對象。若 contextTypes 已經在子組件中定義好了,那在組件接下來的生命周期里將多增加一個參數: context對象
當一個無狀態函數型的組件中定義好一個property並且設置好了 contextTypes ,那該函數也能夠成功引用 context 對象
function Button(props, context) { return ( <button style={{background: context.color}}> {props.children} </button>
); } Button.contextTypes = {color: React.PropTypes.string};
那我們應該怎么更新組件的 Context 呢。答案是,把 Context 和組件的 State關聯起來,當組件的state或者props改變的時候,getChildContext函數會自動調用,更新Context 並把這個新的Context和其他改變一起傳輸到子樹。下面是一個例子
var MediaQuery = React.createClass({ getInitialState: function(){ return {type:'desktop'}; }, childContextTypes: { type: React.PropTypes.string }, getChildContext: function() { return {type: this.state.type}; }, componentDidMount: function(){ var checkMediaQuery = function(){ var type = window.matchMedia("(min-width: 1025px)").matches ? 'desktop' : 'mobile'; if (type !== this.state.type){ this.setState({type:type}); } }; window.addEventListener('resize', checkMediaQuery); checkMediaQuery(); }, render: function(){ return this.props.children; } });
其實在大多數情況下,為了代碼的清晰可觀,我們都應該盡可能避免使用Context(就像全局變量一樣)。Context的最佳應用情景應該是像用戶登錄、應用語言或者是應用主題的這一類情景,這些都是真實的全局變量。
建議不要使用Context在組件中傳輸我們的model data,之前的寫法才會讓代碼簡單易懂。