在React
中很容易根据组件从而跟踪数据流,当你使用一个组件时,可以通过看props
来判断用了哪一些东西。
有时候你想直接通过组件树来讲数据传递子元素,而不是通过props
一层一层的传递下去,可以使用Reac
t提供的contextAPI
来处理。
1.为什么一般都不使用Context
虽然React
提供了context
来处理以上事件 ,但是一般情况下是不需要使用这个API
的。
如果你想要你的应用尽可能的稳定的话,请不要使用Context
,因为这在React
属于一种实验性质的API
,在未来的React
版本中可能被抛弃。
如果你不是一个非常有经验的开发人员,也请不要使用context
,通常都有更好方法来实现我们的要求
如果你硬是要用Context
,请在小范围中使用
2.使用context
的方法
class Button extends React.Component {
render() {
return (
<button style={{background: this.props.color}}>
{this.props.children}
</button>
);
}
}
class Message extends React.Component {
render() {
return (
<div>
{this.props.text} <Button color={this.props.color}>Delete</Button>
</div>
);
}
}
class MessageList extends React.Component {
render() {
const color = "purple";
const children = this.props.messages.map((message) =>
<Message text={message.text} color={color} key={index} />
);
return <div>{children}</div>;
}
}
上面的我们给button
设置颜色,竟然要从顶层的组件一步一步的通过props
传递下去,很烦。
如果是使用context
就会非常简单了
class Button extends React.Component {
render() {
return (
<button style={{background: this.context.color}}>
{this.props.children}
</button>
);
}
}
@H_301_155@//重点
Button.contextTypes = {
color: React.PropTypes.string
};
class Message extends React.Component {
render() {
return (
<div>
{this.props.text} <Button>Delete</Button>
</div>
);
}
}
class MessageList extends React.Component {
@H_301_155@//重点
getChildContext() {
return {color: "purple"};
}
render() {
const children = this.props.messages.map((message,index) =>
<Message text={message.text} key={index}/>
);
return <div>{children}</div>;
}
}
@H_301_155@//重点
MessageList.childContextTypes = {
color: React.PropTypes.string
};
通过childContextTypes
和getChildContext
给MessageList
增加context
上下文,React
会自动将它传递给子组件,如果子组件设置了contextTypes
就会获取到这个上下文。如果子组件的contextTypes
没有设置的话,context
就会是一个空的。
3.父子耦合
context
可以让父组件和子组件建立一个直接数据交流的通道,React Router V4
就实现了这个功能,这里不详讲。
4.在生命周期函数中使用context
需要将context
通过参数传递
constructor(props,context) componentWillReceiveProps(nextProps,nextContext) shouldComponentUpdate(nextProps,nextState,nextContext) componentWillUpdate(nextProps,nextContext) componentDidUpdate(prevProps,prevState,prevContext)
上面这些函数以后会讲解
5.无状态函数式组件中的context
这里先声明一下函数式组件本身无法使用this.state来进行状态标记控制
const Button = ({children},context) => <button style={{background: context.color}}> {children} </button>; Button.contextTypes = {color: React.PropTypes.string};
当我们将context
当做参数传入函数式组件,并且contextTypes
进行了类型检测控制,就可以在函数式组件内部使用context
6.更新Context
虽然React
有更新Context
的函数,但是对不起,依旧不希望你去使用context
,这算是警告中的警告了。
在前面写的时候,我就已经使用getChildContext
来处理数据,这个函数会在state
和props
改变时被调用。只要对state
和props
进行更新就可以实现context
的更新。
class MediaQuery extends React.Component {
constructor(props) {
super(props);
this.state = {type:'desktop'};
}
getChildContext() {
return {type: this.state.type};
}
componentDidMount() {
const checkMediaQuery = () => {
const type = window.matchMedia("(min-width: 1025px)").matches ? 'desktop' : 'mobile';@H_301_155@//这个是用来识别是PC端还是移动端(IE10+)
if (type !== this.state.type) {
this.setState({type});
}
};
window.addEventListener('resize',checkMediaQuery);
checkMediaQuery();
}
render() {
return this.props.children;
}
}
MediaQuery.childContextTypes = {
type: React.PropTypes.string
};
当然使用这个更新也会出问题,就是我们的shouldComponentUpdate
函数返回false
的时候,会导致子组件不更新状态,从而让子组件的context
超出控制。
下一篇将讲
React
中的WEB
组件