Contexts 是React的一個(gè)重要屬性,但是到目前為止,這個(gè)屬性在正式的文檔里面還沒有對(duì)它進(jìn)行正式介紹,在 reactv0.1.4將會(huì)正式發(fā)布這個(gè)屬性。下面先來介紹一下它的使用方式。
React.withContext會(huì)執(zhí)行一個(gè)指定的上下文信息的回調(diào)函數(shù),任何在這個(gè)回調(diào)函數(shù)里面渲染的組件都有這個(gè)context的訪問權(quán)限。
varA = React.createClass({? ?
contextTypes: {? ? ? ?
name: React.PropTypes.string.isRequired,? ?
},? ?
render:function(){
return
My name is: {this.context.name}
;}});React.withContext({'name':'Jonas'},function(){// Outputs: "My name is: Jonas"React.render(
, document.body);});
任何想訪問context里面的屬性的組件都必須顯式的指定一個(gè)contextTypes的屬性。如果沒有指定改屬性,那么組件通過 this.context 訪問屬性將會(huì)出錯(cuò)。
如果你為一個(gè)組件指定了context,那么這個(gè)組件的子組件只要定義了contextTypes 屬性,就可以訪問到父組件指定的context了。
varA = React.createClass({? ? render:function(){return;}});varB = React.createClass({? ? contextTypes: {? ? ? ? name: React.PropTypes.string? ? },? ? render:function(){return
My name is: {this.context.name}
;}});React.withContext({'name':'Jonas'},function(){? React.render(
, document.body);});
為了減少文件的引用,你可以為contextTypes放到一個(gè)minx 中,這樣 用到的組件引用這個(gè)minx就行了。
varContextMixin = {? ? contextTypes: {? ? ? ? name: React.PropTypes.string.isRequired? ? },? ? getName:function(){returnthis.context.name;? ? }};varA = React.createClass({? ? mixins: [ContextMixin],? ? render:function(){return
My name is {this.getName()}
;}});React.withContext({'name':'Jonas'},function(){// Outputs: "My name is: Jonas"React.render(
, document.body);});
getChildContext
和訪問context 的屬性是需要通過contextTypes指定可訪問的 元素一樣。getChildContext指定的傳遞給子組件的屬性需要先通過childContextTypes來指定,不然會(huì)產(chǎn)生錯(cuò)誤。
// This code *does NOT work* becasue of a missing property from childContextTypesvarA = React.createClass({? ? childContextTypes: {// fruit is not specified, and so it will not be sent to the children of Aname: React.PropTypes.string.isRequired? ? },? ? getChildContext:function(){return{? ? ? ? ? ? name:"Jonas",? ? ? ? ? ? fruit:"Banana"};? ? },? ? render:function(){return;}});varB = React.createClass({? ? contextTypes: {? ? ? ? fruit: React.PropTypes.string.isRequired? ? },? ? render:function(){return
My favorite fruit is: {this.context.fruit}
;}});// Errors: Invariant Violation: A.getChildContext(): key "fruit" is not defined in childContextTypes.React.render(
, document.body);
假設(shè)你的應(yīng)用程序有多層的context。通過withContext和getChildContext指定的context元素都可以被子組件引用。但是子組件是需要通過contextTypes來指定所需要的context 元素的。
varA = React.createClass({? ? childContextTypes: {? ? ? ? fruit: React.PropTypes.string.isRequired? ? },? ? getChildContext:function(){return{ fruit:"Banana"};? ? },? ? render:function(){return;}});varB = React.createClass({? ? contextTypes: {? ? ? ? name: React.PropTypes.string.isRequired,? ? ? ? fruit: React.PropTypes.string.isRequired? ? },? ? render:function(){return
My name is: {this.context.name} and my favorite fruit is: {this.context.fruit}
;}});React.withContext({'name':'Jonas'},function(){// Outputs: "My name is: Jonas and my favorite fruit is: Banana"React.render(
, document.body);});
context 是就近引用的,如果你通過withContext指定了context元素,然后又通過getChildContext指定了該元素,該元素的值將會(huì)被覆蓋。
varA = React.createClass({? ? childContextTypes: {? ? ? ? name: React.PropTypes.string.isRequired? ? },? ? getChildContext:function(){return{ name:"Sally"};? ? },? ? render:function(){return;}});varB = React.createClass({? ? contextTypes: {? ? ? ? name: React.PropTypes.string.isRequired? ? },? ? render:function(){return
My name is: {this.context.name}
;}});React.withContext({'name':'Jonas'},function(){// Outputs: "My name is: Sally"React.render(
, document.body);});
總結(jié)
通過context傳遞屬性的方式可以大量減少 通過顯式的通過props逐層傳遞屬性的方式。這樣可以減少組件之間的直接依賴關(guān)系。