理解React反向数据流

文章目录

在React中数据传递是按组件一级一级传递的,因为这样可以很清楚数据的流向,但也会造成一个问题,就是当用户在深层的组件中输入数据,程序取得用户数据后,无法在当前组件中传递数据到其它层级组件,而只能通过把数据回传上级组件来把数据传递到其它组件(反向数据流),React这样做的好处就是让数据流向一直保持清晰可见,下面的Todo list就可以很好的理解这一点

Add TodoList.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Product</title>
<script src="https://www.myfreax.com/understanding-react-reverse-data-stream/build/lib/react.js"></script>
<script src="https://www.myfreax.com/understanding-react-reverse-data-stream/build/lib/react-dom.js"></script>
<script src="https://www.myfreax.com/understanding-react-reverse-data-stream/build/lib/browser.min.js"></script>
<script src="https://www.myfreax.com/understanding-react-reverse-data-stream/build/lib/jquery.min.js"></script>
<script src="https://www.myfreax.com/understanding-react-reverse-data-stream/build/lib/marked.min.js"></script>
</head>
<body>
<div id="todolist">
</div>
</body>
<script src="https://www.myfreax.com/understanding-react-reverse-data-stream/build/TodoList/Row.js" type="text/javascript"></script>
<script src="https://www.myfreax.com/understanding-react-reverse-data-stream/build/TodoList/List.js" type="text/javascript"></script>
<script src="https://www.myfreax.com/understanding-react-reverse-data-stream/build/TodoList/TodoForm.js" type="text/javascript"></script>
<script src="https://www.myfreax.com/understanding-react-reverse-data-stream/build/TodoList/TodoList.js" type="text/javascript"></script>
</html>

TodoList组件

/**
* Created by huangyanxiong on 16-3-11.
*/
var TodoList = React.createClass({
/**
* 初始化数据
* @returns {{todo: string}}
*/
getInitialState: function () {
return {todos:[],todo:''};
},
/**
*  处理下一级组件上传的值,即处理反向数据流
*/
handleTodoSubmit: function (todo) {
this.state.todos.push(todo);    //取得用户输入的数据并且推进的todos数组中
this.setState(this.state.todos);    //设置状态,更新组件
},
render: function () {
return (
<div className="todoList">
<h1>TODO</h1>
<TodoForm handletodosubmit={this.handleTodoSubmit}/>
<List todos={this.state.todos}/>
</div>
);
}
});
ReactDOM.render(<TodoList/>,document.getElementById('todolist'));

List

var List = React.createClass({
render: function () {
var rows = this.props.todos.map(function (todo) {
return <Row todo={todo} key={todo}/>
});
return (
<ul className="list">
{rows}
</ul>
);
}
});

Row组件

/**
* Created by huangyanxiong on 16-3-11.
*/
var Row = React.createClass({
render: function () {
return (
<li>
{this.props.todo}
</li>
);
}
});

TodoForm组件

/**
* Created by huangyanxiong on 16-3-11.
*/
var TodoForm = React.createClass({
handleSubmit: function (e) {
e.preventDefault();
/**
* 数据反向流入口,传递数据到上级组件
* 取得用户输入的表单值,接着需要把放在list中
* 由于React数据传递是一级一级传递的,所以只能把数据传递上级组件TodoList,然后由TodoList传递给 List
* List组件才能接收到用户添加的Todo,并添加到List组件
* 这就是反向数据流 TodoForm > TodoList
* 当用户点击添加Add事件,整个数据流向
* TodoForm > TodoList > List > Row
*/
if (!this.refs.todo.value){
alert('todo is not null');
return false;
}
this.props.handletodosubmit(this.refs.todo.value.toString());
this.refs.todo.value = '';
},
render: function () {
return (
<form onSubmit={this.handleSubmit}>
<input type="text" ref="todo"/>
<button>Add #3</button>
</form>
)
}
});

在这个Todo list划分了四个组件分别是TodoList,List,Row,TodoForm

初始化时的数据流

在组件初始化渲染时可以很清晰的看到React数据时一级一级传递

TodoList > List > Row

在这时程序是不能取得用户输入的数据的,这只是一个静态版本todo list,当用户在TodoForm组件中数据并通过onSubmit事件取得用户数据,会发现数据不能在TodoForm组件中传递到List组件,为了解决这个问题,React也就引入另一个概念:反向数据流

用户提交时数据流

TodoForm > TodoList

TodoForm组件数据回传TodoList,在TodoList组件中使用this.setState(this.state.todos)更新组件,从而使数据可以传递到其它组件,来达到数据双向绑定

TodoForm > TodoList > List > Row

而对于Angular框架的双向绑定,$scopeController以及模板的数据双向绑定,对于我们来说透明的,隐藏了复杂性,可以少做很多工作,React则没有这么做,但是让我们很好的理解应用是怎么工作的

全部为采集文章,文中的 联系方式 均不是 本人 的!

发表评论