1、React.withContext会执行一个指定上下文信息的回调函数,任何在这个回调函数里面渲染的组件都有这个context访问权限(我对这句话的理解是:为这个组件指定了context)
(1)情况一:任何想访问context里面的属性的组件都必须显示的指定一个contextTypes的属性,如果没有指定该属性,那么组件通过this.context访问属性将会出错。
var A = React.createClass({
contextTypes: {
name: React.PropTypes.string.isRequired,
},
render: function() {
return <div>My name is: {this.context.name}</div>;
}
});
React.withContext({'name': 'Jonas'}, function () {
React.render(<A />, document.body);//"My name is: Jonas"
});
(2)情况二:如果你为一个组件(这里指组件A)指定了context,那么这个组件的子组件(这里指组件B)只要定义了contextTypes,就可以访问到父组件指定的context了。
var A = React.createClass({
render: function() {
return <B />;
}
});
var B = React.createClass({
contextTypes: {//这里指定了contextTypes,因此下边的子组件B就可以通过this.context来访问父组件的内容了
name: React.PropTypes.string
},
render: function() {
return <div>My name is: {this.context.name}</div>;
}
});
React.withContext({'name': 'Jonas'}, function () {
React.render(<A />, document.body);
});
(3)上边情况二中可以看出我们会在文件中引入两个组件,那为了减少文件的引用,我们可以把contextTypes放在minx中,这样用到的组件引用这个minx就可以了。
var ContextMixin = {
contextTypes: {
name: React.PropTypes.string.isRequired
},
getName: function() {
return this.context.name;
}
};
var A = React.createClass({
mixins: [ContextMixin],
render: function() {
return <div>My name is {this.getName()}</div>;
}
});
React.withContext({'name': 'Jonas'}, function () {
React.render(<A />, document.body);//"My name is: Jonas"
});
2、getChildContext:与访问context属性需要通过contextTypes指定可访问的属性一样,getChildContext指定的传递给子组件的属性需要先通过childContextTypes来执行,不然会报错。
(1)情况一:
// This code *does NOT work* becasue of a missing property from childContextTypes
var A = React.createClass({
childContextTypes: {//用于说明所传递的数据类型
// fruit is not specified, and so it will not be sent to the children of A
name: React.PropTypes.string.isRequired
},
getChildContext: function() {//getChildContext表示该组件通过context传递数据,该方法返回的对象就是context需要传递的数据
return {
name: "Jonas",
fruit: "Banana"
};
},
render: function() {
return <B />;
}
});
var B = React.createClass({
contextTypes: {//在子组件中用于说明context接收的数据类型
fruit: React.PropTypes.string.isRequired
},
render: function() {
return <div>My favorite fruit is: {this.context.fruit}</div>;
}
});
// Errors: Invariant Violation: A.getChildContext(): key "fruit" is not defined in childContextTypes.
React.render(<A />, document.body);
(2)情况二:假设应用程序有多层的context。通过withContext和getChildContext指定的context元素都可以被子组件引用。但是子组件是需要通过contextTypes来指定所需要的context元素的。
var A = React.createClass({
childContextTypes: {
fruit: React.PropTypes.string.isRequired
},
getChildContext: function() {
return { fruit: "Banana" };
},
render: function() {
return <B />;
}
});
var B = React.createClass({
contextTypes: {
name: React.PropTypes.string.isRequired,
fruit: React.PropTypes.string.isRequired
},
render: function() {
return <div>My name is: {this.context.name} and my favorite fruit is: {this.context.fruit}</div>;
}
});
React.withContext({'name': 'Jonas'}, function () {
React.render(<A />, document.body);//"My name is: Jonas and my favorite fruit is: Banana"
});
(3)context是就近引用的,如果你通过withContext指定了context元素,然后又通过getChildContext指定了该元素,该元素的值将会被覆盖。
var A = React.createClass({
childContextTypes: {
name: React.PropTypes.string.isRequired
},
getChildContext: function() {
return { name: "Sally" };
},
render: function() {
return <B />;
}
});
var B = React.createClass({
contextTypes: {
name: React.PropTypes.string.isRequired
},
render: function() {
return <div>My name is: {this.context.name}</div>;
}
});
React.withContext({'name': 'Jonas'}, function () {
React.render(<A />, document.body);//"My name is: Sally"
});
总结:通过context传递属性的方式可以大量减少通过props逐层传递属性的方式,这样可以直接减少组件之间的依赖关系(我之前有一篇文章提到了context可以跨组件传值,大概就是这个意思吧~)
参考文章:
React 中使用context实现数据穿越
react中context学习
相关文章:
深入浅出React高阶组件
React进阶之高阶组件
网友评论