React 组件数据流 && 组件间沟通
使用React我们首先要知道如何传递数据,组件如何沟通,才能展示我们想要的数据。下面的列子都是使用ES6语法,不懂的同学需要先学习ES6语法。 数据流React是单向数据流,从父节点传递到子节点(通过 Props
class Component { constructor(props){ super(props); } render(){ return ( <div title={this.props.title}></div> ) } } <Component title="test"/>//调用title就传进去了 PropTypes
class Component { ... } Component.PropsType = { title: React.PropTypes.string,}
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!'); } } },/* ... */ }); defaultProps如何设置组件默认的 //React提供的crateClass创建方式 var Component = React.createClass({ getDefaultProps(){ return { //这里设置defaultProps } } }) //ES6 class Component { ... } Component.defaultProps = {} //ES7 stage-0 class Component { static defaultProps = { } ... } state每个组件都有属于自己的 那如何设置默认state? //React提供的crateClass创建方式 var Component = React.createClass({ getInitialState(){ return { //这里设置初始state值 } } }) //ES6 && ES7 class Component { constructor(){ this.state = {}//在ES6中的构造函数中初始化,可以之直接赋值,在其他方法中,只能使用this.setState } ... } props和state使用方式尽可能使用 组件沟通组件沟通因为React的单向数据流方式会有所限制,下面述说组件之间的沟通方式。 父子组件沟通这种方式是最常见的,也是最简单的。
父组件更新子组件状态,通过传递
这种情况需要父组件传递回调函数给子组件,子组件调用触发即可。 代码示例: 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单向数据流方式,我们需要借助父组件进行传递,通过父组件回调函数改变兄弟组件的 方式一通过 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 全局事件
官网中提到可以使用全局事件来进行组件间的通信,官网推荐Flux(Facebook官方出的),还有Relay、Redux、trandux等第三方类库。这些框架思想都一致,都是统一管理组件state变化情况,达到数据可控目的。本人使用了Redux,建议要会其中一种。对于EventEmitter或PostalJS这类的第三方库是不建议使用的,这类全局事件框架并没有统一管理组件数据变化,用多了会导致数据流不可控。 这里就不细说,请选择其中一种类库,深入学习下。 总结简单的组件交流我们可以使用上面非全局事件的简单方式,但是当项目复杂,组件间层次越来越深,上面的交流方式就不太合适(当然还是要用到的,简单的交流)。强烈建议使用Flux、Relay、Redux、trandux等类库其中一种,这些类库不只适合React,像Angular等都可以使用。 参考文章
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |