在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>
);
}
}
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 {
getChildContext() {
return {color: "purple"};
}
render() {
const children = this.props.messages.map((message,index) =>
<Message text={message.text} key={index}/>
);
return <div>{children}</div>;
}
}
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';
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 组件
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|