二十、用上下文管理应用
来源:互联网 发布:xmind for mac 序列号 编辑:程序博客网 时间:2024/05/16 20:28
二十、用上下文管理应用
使用React可以很容易通过React组件跟踪数据流。 当你看到一个组件,你就可以看到哪些props
正在传递,这使得你的应用很容易知道在做什么。
在某些情况下,你希望通过组件树传递数据,而不是在每个级别的中组件手动传递props
,你可以直接在React中使用强大的“context”
来做到这一点。
为什么不去使用Context
绝大多数的应用不需要直接使用Context。
如果你希望你的应用是稳定的,那么就不要使用Context。 因为这是一个实验性质的API,它可能会在未来的React版本中移除。
如果你不熟悉state管理库如Redux
或MobX
,不要使用Context。 对于许多实际的应用,这些state管理库和React一起使用来管理那些与组件相关的state一个很不错的选择。 很多情况下使用Redux
就可以解决你的问题,而不是使用Context。
如果你不是一个有经验的React开发人员,不要使用Context。 使用props
和state
来实现功能是一个更好的方法。
尽管有上面这些警告你还坚持使用Context,那么请将Context单独隔离到一个小区域中,并尽可能地避免直接使用Context,以便在这个API更改时应用能更容易升级。
如何使用Context
假设你有一个结构:
import React from 'react';import ReactDOM from 'react-dom';class MyButton extends React.Component { constructor(props) { super(props); } render() { const style = {backgroundColor: this.props.color}; return <button style={style}>{this.props.children}</button>; }}class Message extends React.Component { render() { return ( <div> {this.props.text} <MyButton color={this.props.color}>删除</MyButton> </div> ) }}class MessageList extends React.Component { render() { const color = 'red'; const children = this.props.messages.map(msg => <Message text={msg} color={color}/>); return <div>{children}</div>; }}const messages = ['zhangyato', 'Re: zhangyatao', 'Re:Re:zhangyatao'];ReactDOM.render( <MessageList messages={messages}/>, document.getElementById('root'));
在这个例子中,我们手动传入一个color
props进行传递,以便适当地设置MyButton
和Message
组件的样式。 使用Context,我们可以让color
自动在组件树中传递:
import React from 'react';import ReactDOM from 'react-dom';class MyButton extends React.Component { constructor(props) { super(props); } render() { const style = {backgroundColor: this.context.color}; return <button style={style}>{this.props.children}</button>; }}MyButton.contextTypes = { color: React.PropTypes.string.isRequired};class Message extends React.Component { render() { return ( <div> {this.props.text} <MyButton>删除</MyButton> </div> ) }}class MessageList extends React.Component { getChildContext() { return {color: 'red'}; } render() { const children = this.props.messages.map(msg => <Message text={msg}/>); return <div>{children}</div>; }}MessageList.childContextTypes = { color: React.PropTypes.string.isRequired};const messages = ['zhangyato', 'Re: zhangyatao', 'Re:Re:zhangyatao'];ReactDOM.render( <MessageList messages={messages}/>, document.getElementById('root'));
通过向MessageList
(Context提供者)添加childContextTypes
和getChildContext
,React就会自动传递Context信息,子组件树中的任何组件(Button
)都可以通过定义contextTypes
来访问它。
如果未定义contextTypes
,那么Context将是一个空对象。
父子组件之间的耦合
Context还可以让你实现父组件和子组件之间的交互。 例如,以这种方式工作的一个比较知名的库为React Router V4
:
const RouterExample = () => { <Router> <div> <ul> <li><Link to="/">主页</Link></li> <li><Link to="/recyclebin">回收站</Link></li> <li><Link to="/timeline">图片</Link></li> </ul> <hr /> <Match exactly pattern="/" component={Home} /> <Match pattern="/recyclebin" component={RecycleBin} /> <Match pattern="/timeline" component={TimeLine} /> </div> </Router>}
通过从RouterExample
组件传递一些信息,每个Link
和Match
可以回传到包含的Router
中。
在使用类似于此的API进行构建组件之前,请考虑是否有更好的替代品。 例如,你可以传递整个React组件作为props。
生命周期方法中使用Context
如果在一个组件中定义了contextTypes
,则以下生命周期方法将多接收个参数,就是Context对象:
constructor(props, context)
componentWillReceiveProps(nextProps, nextContext)
shouldComponentUpdate(nextProps, nextState, nextContext)
componentWillUpdate(nextProps, nextState, nextContext)
componentDidUpdate(prevProps, prevState, prevContext)
在无状态功能性组件中使用Context
如果contextTypes
被定义为无状态功能性组件的属性,无状态功能性组件也能够引用Context。 下面的代码显示了被写成一个无状态的功能组件的MyButton
组件。
function MyButton(props, context) { const children = props.children; return ( <button style={{backgroundColor: context.color}}> {children} </button> );}MyButton.contextTypes = { color: React.PropTypes.string.isRequired};
更新Context
千万不要这么做!!!
React有一个API来更新Context,但它从根本上破坏了Context,所以你不应该使用它。
当state或props改变时,getChildContext
函数将被调用。 为了更新Context中的数据,使用this.setState()
触发组件内的state更新。 这也将触发一个新的Context,并且Context改变的内容也会被子组件接收到。
import React from 'react';import ReactDOM from 'react-dom';class MediaType extends React.Component { render() { return <div>type is {this.context.type}</div> }}MediaType.contextTypes = { type: React.PropTypes.string};class MediaQuery extends React.Component { constructor(props) { super(props); this.state = {type: 'PC端'}; this.checkMediaQuery = this.checkMediaQuery.bind(this); } getChildContext() { return {type: this.state.type} } checkMediaQuery() { let type = window.matchMedia('<code>zhangyatao</code>(max-width: 760px)').matches ? '移动端' : 'PC端'; this.setState({type: type}); } componentDidMount() { window.addEventListener('resize', this.checkMediaQuery, false); this.checkMediaQuery(); } render() { return <div>{this.props.children}</div>; }}MediaQuery.childContextTypes = { type: React.PropTypes.string};ReactDOM.render( <MediaQuery> <MediaType /> </MediaQuery>, document.getElementById('root'));
问题是,Context的值通过组件更新来提供,如果中间的父组件在shouldComponentUpdate()
返回false,那么使用该Context值的后代组件永远不会被更新。使用Context完全不受组件的控制,所以基本上没有办法可靠地更新Context。 这篇文章很好的解释了为什么这是一个问题,以及你应该如何摆脱它。
- 二十、用上下文管理应用
- Oracle12C--用户管理(二十)
- Unix/Linux C++应用开发-Linux下文件管理
- Unix/Linux C++应用开发-Linux下文件管理
- 十问 Linux 虚拟内存管理 (glibc) (二)
- 十问 Linux 虚拟内存管理 (glibc) (二)
- 十问 Linux 虚拟内存管理 (glibc) (二)
- 二十、管理后台的权限控制
- linux下文件管理
- linux下文件管理
- Autofac官方文档(二十)【应用集成】
- openstack 命令行管理二十 - instance novnc 访问管理 (备忘)
- Swing鼠标悬停时巧用上下文菜单显示提示信息
- Swing鼠标悬停时巧用上下文菜单显示提示信息
- C# 系统应用之ListView控件 (二).加载选中节点文件夹下文件信息
- C# 系统应用之ListView控件 (二).加载选中节点文件夹下文件信息
- 从此小白都用上了cocoapods管理第三方
- 从十大经典故事学管理之二
- Metropolis-Hasting 算法 & 图上的Metropolis-Hasting Random Walk (MHRW)
- openSession()到底做了什么
- Java设计模式之观察者模式
- 学习unity能够做什么
- 5 函数的定义和调用应用实例
- 二十、用上下文管理应用
- Python 字符串常用函数
- MonkeyRunner:Android自动化测试
- Salesforce 知识整理
- mysqldump大致原理以及mysqldump备份过程中进行DDL操作的影响
- LINUX守护进程
- 怎样实现UDP可靠传输
- android 设定wifi SSID和MAC地址的绑定
- docker镜像仓库介绍