使用React咱们首先要知道如何传递数据,组件如何沟通,才能展现咱们想要的数据。下面的列子都是使用ES6语法,不懂的同窗须要先学习ES6语法。node
React是单向数据流,从父节点传递到子节点(经过props
)。若是顶层的某个props
改变了,React会重渲染全部的子节点(未作性能优化)。严格意义上React只提供,也强烈建议使用这种数据交流方式。react
props
是property的缩写,能够理解为HTML标签的attribute。请把props
当作只读的(不可使用this.props
直接修改props),props
是用于整个组件树中传递数据和配置。在当前组件访问props
,使用this.props
。在什么状况下可使用props
,请看组件生命周期git
class Component { constructor(props){ super(props); } render(){ return ( <div title={this.props.title}></div> ) } } <Component title="test"/>//调用title就传进去了
PropsTypes
是React中用来定义props
的类型,不符合定义好的类型会报错。建议可复用组件要使用prop验证!接着上面的列子设置PropsTypes
以下:github
class Component { ... } Component.PropsType = { title: React.PropTypes.string, }
React.PropTypes
提供不少验证器 (validator) 来验证传入数据的有效性。官方定义的验证器以下,不是使用ES6语法。redux
React.createClass({ propTypes: { // 能够声明 prop 为指定的 JS 基本类型。默认 // 状况下,这些 prop 都是可传可不传的。 optionalArray: React.PropTypes.array, optionalBool: React.PropTypes.bool, optionalFunc: React.PropTypes.func, optionalNumber: React.PropTypes.number, optionalObject: React.PropTypes.object, optionalString: React.PropTypes.string, optionalSymbol: React.PropTypes.symbol, // 全部能够被渲染的对象:数字, // 字符串,DOM 元素或包含这些类型的数组(or fragment) 。 optionalNode: React.PropTypes.node, // React 元素 optionalElement: React.PropTypes.element, // 你一样能够断言一个 prop 是一个类的实例。 // 用 JS 的 instanceof 操做符声明 prop 为类的实例。 optionalMessage: React.PropTypes.instanceOf(Message), // 你能够用 enum 的方式 // 确保你的 prop 被限定为指定值。 optionalEnum: React.PropTypes.oneOf(['News', 'Photos']), // 指定的多个对象类型中的一个 optionalUnion: React.PropTypes.oneOfType([ React.PropTypes.string, React.PropTypes.number, React.PropTypes.instanceOf(Message) ]), // 指定类型组成的数组 optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number), // 指定类型的属性构成的对象 optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number), // 特定形状参数的对象 optionalObjectWithShape: React.PropTypes.shape({ color: React.PropTypes.string, fontSize: React.PropTypes.number }), // 你能够在任意东西后面加上 `isRequired` // 来确保 若是 prop 没有提供 就会显示一个警告。 requiredFunc: React.PropTypes.func.isRequired, // 不可空的任意类型 requiredAny: React.PropTypes.any.isRequired, // 你能够自定义一个验证器。若是验证失败须要返回一个 Error 对象。 // 不要直接使用 `console.warn` 或抛异常, // 由于这在 `oneOfType` 里不起做用。 customProp: function(props, propName, componentName) { if (!/matchme/.test(props[propName])) { return new Error('Validation failed!'); } } }, /* ... */ });
如何设置组件默认的props
?segmentfault
//React提供的crateClass建立方式 var Component = React.createClass({ getDefaultProps(){ return { //这里设置defaultProps } } }) //ES6 class Component { ... } Component.defaultProps = {} //ES7 stage-0 class Component { static defaultProps = { } ... }
每一个组件都有属于本身的state
,state
和props
的区别在于前者之只存在于组件内部,只能从当前组件调用this.setState
修改state值(不能够直接修改this.state
)。通常咱们更新子组件都是经过改变state
值,更新新子组件的props
值从而达到更新。数组
那如何设置默认state?性能优化
//React提供的crateClass建立方式 var Component = React.createClass({ getInitialState(){ return { //这里设置初始state值 } } }) //ES6 && ES7 class Component { constructor(){ this.state = {}//在ES6中的构造函数中初始化,能够之直接赋值,在其余方法中,只能使用this.setState } ... }
尽量使用props
当作数据源,state
用来存放状态值(简单的数据),如复选框、下拉菜单等。架构
组件沟通由于React的单向数据流方式会有所限制,下面述说组件之间的沟通方式。框架
这种方式是最多见的,也是最简单的。
父组件更新组件状态
父组件更新子组件状态,经过传递props
,就能够了。
子组件更新父组件状态
这种状况须要父组件传递回调函数给子组件,子组件调用触发便可。
代码示例:
class Child extends React.Component{ constructor(props){ super(props); this.state = {} } render(){ return ( <div> {this.props.text} <br /> <button onClick={this.props.refreshParent}> 更新父组件 </button> </div> ) } } class Parent extends React.Component{ constructor(props){ super(props); this.state = {} } refreshChild(){ return (e)=>{ this.setState({ childText: "父组件沟通子组件成功", }) } } refreshParent(){ this.setState({ parentText: "子组件沟通父组件成功", }) } render(){ return ( <div> <h1>父子组件沟通</h1> <button onClick={this.refreshChild()} > 更新子组件 </button> <Child text={this.state.childText || "子组件未更新"} refreshParent={this.refreshParent.bind(this)} /> {this.state.parentText || "父组件未更新"} </div> ) } }
codepen例子React组件之父子组件沟通 。
当两个组件有相同的父组件时,就称为兄弟组件(堂兄也算的)。按照React单向数据流方式,咱们须要借助父组件进行传递,经过父组件回调函数改变兄弟组件的props
。
经过props
传递父组件回调函数。
class Brother1 extends React.Component{ constructor(props){ super(props); this.state = {} } render(){ return ( <div> <button onClick={this.props.refresh}> 更新兄弟组件 </button> </div> ) } } class Brother2 extends React.Component{ constructor(props){ super(props); this.state = {} } render(){ return ( <div> {this.props.text || "兄弟组件未更新"} </div> ) } } class Parent extends React.Component{ constructor(props){ super(props); this.state = {} } refresh(){ return (e)=>{ this.setState({ text: "兄弟组件沟通成功", }) } } render(){ return ( <div> <h2>兄弟组件沟通</h2> <Brother1 refresh={this.refresh()}/> <Brother2 text={this.state.text}/> </div> ) } }
codepen例子:React组件之兄弟组件沟通。
可是若是组件层次太深(以下图),上面的兄弟组件沟通方式就效率低了(不建议组件层次太深)。
React提供了一种上下文方式(挺方便的),可让子组件直接访问祖先的数据或函数,无需从祖先组件一层层地传递数据到子组件中。
class Brother1 extends React.Component{ constructor(props){ super(props); this.state = {} } render(){ return ( <div> <button onClick={this.context.refresh}> 更新兄弟组件 </button> </div> ) } } Brother1.contextTypes = { refresh: React.PropTypes.any } class Brother2 extends React.Component{ constructor(props){ super(props); this.state = {} } render(){ return ( <div> {this.context.text || "兄弟组件未更新"} </div> ) } } Brother2.contextTypes = { text: React.PropTypes.any } class Parent extends React.Component{ constructor(props){ super(props); this.state = {} } getChildContext(){ return { refresh: this.refresh(), text: this.state.text, } } refresh(){ return (e)=>{ this.setState({ text: "兄弟组件沟通成功", }) } } render(){ return ( <div> <h2>兄弟组件沟通</h2> <Brother1 /> <Brother2 text={this.state.text}/> </div> ) } } Parent.childContextTypes = { refresh: React.PropTypes.any, text: React.PropTypes.any, }
codepen例子:React组件之兄弟组件沟通2
For communication between two components that don't have a parent-child relationship, you can set up your own global event system. Subscribe to events in
componentDidMount()
, unsubscribe incomponentWillUnmount()
, and callsetState()
when you receive an event.Flux pattern is one of the possible ways to arrange this.
官网中提到可使用全局事件来进行组件间的通讯,官网推荐Flux(Facebook官方出的),还有Relay、Redux、trandux等第三方类库。这些框架思想都一致,都是统一管理组件state变化状况,达到数据可控目的。本人使用了Redux,建议要会其中一种。对于EventEmitter或PostalJS这类的第三方库是不建议使用的,这类全局事件框架并无统一管理组件数据变化,用多了会致使数据流不可控。
这里就不细说,请选择其中一种类库,深刻学习下。
简单的组件交流咱们可使用上面非全局事件的简单方式,可是当项目复杂,组件间层次愈来愈深,上面的交流方式就不太合适(固然仍是要用到的,简单的交流)。强烈建议使用Flux、Relay、Redux、trandux等类库其中一种,这些类库不仅适合React,像Angular等均可以使用。