React数据传递和动画的使用及示例
09 May 2016React入门教程
React 是 facebook 开发的一款前端js库,入门使用教程请参考这里
React 的数据传递
React不同于Angular(双向数据绑定),是单向数据绑定,使得数据的流向更加清楚明确,但随着组件的细分,组件与组件之间的通讯数据传递是一个比较有趣的问题。通常 React 组件之间交流的方式,可以分为以下 3 种:
- 【父组件】向【子组件】传值;
- 【子组件】向【父组件】传值;
- 没有任何嵌套关系的组件之间传值(PS:比如:兄弟组件之间传值)
这里简单写了几个示例,简单说明了组件之间的数据传递,示例代码地址。
父组件向子组件传值
这是最常见的,也是 React 正常开发中的常见场景,主要是利用 props 来进行交流。示例代码对应 src/todo-learning.js
//父组件
var Todo = React.createClass({
getInitialState : function(){
...
},
render : function(){
return (
<div className="todo-box">
<div className="input-box">
<input type="text" ref="myTextInput" placeholder="请输入" onKeyUp={this.keyupHander}/>
</div>
<ItemList listWords={this.state.listWords}/>
</div>
)
},
keyupHander: function(ev){
...
}
});
//子组件
var ItemList = React.createClass({
getInitialState : function(){
return {
listData : this.props.listWords
}
},
render : function(){
var \_this = this;
return (
<ul className="list-box">
{
this.state.listData.map(function(json,key){
return (
<li className="list-item" key={key}>
<span className="list-txt">{json.text}</span>
<a href="javascript:;" data-id={json.id} onClick={_this.deleteItem}>删除</a>
</li>
)
})
}
</ul>
)
},
deleteItem : function(ev){
...
}
});
input中输入的内容,通过 keyupHander传递到组件的 state中,子组件ItemList,通过添加属性listWords来向其内部传递数据,在其组件内部,通过 props 属性获取到。
注意:在循环数据时,必须给每项添加key属性,否则会有警告
子组件向父组件传值
React 为单向数据传递,子组件向父组件进行反向数据传递,可以通过,在子组件上绑定props属性,该属性是一个方法,通过该方法的参数,来进行数据的传递,示例代码对应 src/todo-todo.js
//父组件
var Todo = React.createClass({
getInitialState : function(){
return {
'todos' : []
}
},
render : function(){
return (
<div className="todo-box">
<InputText todoInput={this.todoHander}/> // 通过todoInput函数的参数,传递到父组件
<ListBox todos={this.state.todos}/>
</div>
)
},
todoHander : function(todo){
...
}
});
//子组件
var InputText = React.createClass({
render : function(){
return (
<div className="input-box">
<input type="text" placeholder="请输入" onKeyUp={this.inputHander}/>
</div>
)
},
inputHander : function(ev){
...
//通过 props 的函数参数 实现反向数据传递
this.props.todoInput(json);
...
}
});
没有任何嵌套关系的组件之间传值
这种组件之间的数据传递可以借助pubsub.js这个库来实现,该库有两个方法,PubSub.subscribe
订阅事件和PubSub.publish
发布事件,通过在需要变化的组件中订阅一个事件,其他组件中通过发布该事件来变化该组件,示例代码对应 src/todo-adon.js
//父组件
var Todo = React.createClass({
render : function(){
return (
<div className="todo-box">
<InputText />
<ListBox />
</div>
)
},
});
//子组件
var InputText = React.createClass({
render : function(){
return (
<div className="input-box">
<input type="text" placeholder="请输入" onKeyUp={this.inputHander}/>
</div>
)
},
inputHander : function(ev){
...
PubSub.publish('addTodo', json);
...
}
});
//子组件
var ListBox = React.createClass({
getInitialState : function(){
return {
listTodo : []
}
},
render : function(){
...
},
//订阅事件监听数据变化
componentDidMount : function(){
this.pusAdd = PubSub.subscribe('addTodo',function(key,item){
this.state.listTodo.push(item);
this.setState({
listTodo : this.state.listTodo
})
}.bind(this));
//组件自己 订阅事件
this.pubDel = PubSub.subscribe('delTodo',function(key,item){
var arr = this.state.listTodo
$.each(arr,function(index,json){
if(json && json.id == item){
arr.splice(index,1)
}
});
this.setState({
listTodo : arr
});
}.bind(this));
},
//组件卸载时清除订阅事件
componentWillUnmount : function(){
PubSub.unsubscribe(this.pusAdd);
PubSub.unsubscribe(this.pubDel);
},
deleteItem: function(ev){
var id = $(ev.target).attr('data-id');
//组件自己 发送事件
PubSub.publish('delTodo', id);
}
});
注意:pubsub订阅事件需要在组件渲染完再进行订阅(componentDidMount中),组件卸载时也要对订阅事件进行销毁
更多关于React数据传递在segmentfault中有一篇更详细的说明,点击这里
React中的Animate
React为动画提供一个ReactTransitonGroup插件组件作为一个底层的API,一个ReactCSSTransitionGroup来简单地实现基本的CSS动画和过渡。这个的灵感来自于优秀的ng-animate库。示例代码对应 src/todo-animate.js
React的Animate使用需要引入带有插件的React库 react-with-addons.js,参考todo-animate.html
。
ReactTransitonGroup组动画必须要挂载了才能生效,简单说不能放在动态变化的结构中。如下:
...
var item = this.state.listTodo.map(function(json,key){
return (
<li className="list-item" key={key}><span className="list-txt">{json.todo} </span><a href="javascript:;" data-id={json.id} onClick={this.deleteItem}>删除</a></li>
)
}.bind(this));
...
<ul className="list-box">
<ReactCSSTransitionGroup transitionName="slide" transitionEnterTimeout={0} transitionLeaveTimeout={0}>
{item}
</ReactCSSTransitionGroup>
</ul>
代码中{item}
,是会变化的,因此ReactCSSTransitionGroup,不能放在其中,需要放在外面,作为固定的一种结构,另外 transitionEnterTimeout和transitionLeaveTimeout属性需要设置否则会有警告。
注意:你必须为ReactCSSTransitionGroup的所有子级提供键属性,即使只渲染一项。这就是React确定哪一个子级插入了,移除了,或者停留在那里。同之前的key
结束
希望通过本文能帮助更快的上手开发React项目,更多文档介绍请转至React