我最近开始学习 ReactJS。有了 GitHub 上面这个很棒的文档让我觉得它很容易学习。 我用 ReactJS 创建了一个示例应用,而且它工作得很好! 有了一些经验之后,我想先提一下它的两个要点:
然后我听说了 React with Flux,我很想知道为什么当React自身很好的情况下我们还需要Flux(why do we need Flux when React is fine on its own)。 我在 ReactJS 方面没有太多的开发经验,这就是为什么我无法意识到Flux的作用。基于对学习的渴望,我告诉自己振作一点,学习Flux的同时也帮助培训他人。 |
用 ReactJS 创建一个应用,但最初并没有使用 Flux ,这样便于理解它的优势,比如:
为了在实践中有一样的效果,我们来看看使用 Flux 和不使用 Flux 来创建应用程的区别。 让我们从了解 Flux 的基本定义/架构开始。 Flux 框架 |
Flux 有以下四个要点
假设要创建一个 TODO 应用。这是一个单页应用,分为以下几个组件:
在浏览器中,组件将如下图所示: |
预期的特性
|
1
2
3
4
5
6
|
var TodoItem = React.createClass({ render: function() { return ( <li> { this .props.user } - { this .props.task} </li>) } }) |
下面的组件是 TodoList,它负责渲染所有的 todo items。这个组件通过 props 从父类获取“数据”。“this.props.data” 是我们之前创建的用于迭代和调用 TodoItem 的一个列表。
var TodoList = React.createClass({
render: function() {
var TodoTasks = this.props.data.map(function(todoItem) {
return (
< TodoItem user = { todoItem.user } task = {todoItem.task} key = { todoItem.id } />
)
})
return (
< div className = "todo list" >
<ul> Todo List
{TodoTasks}
</ul>
</div>
)
}
});
TodoCount 组件负责显示 items 的计数。 它从 TodoHeader 组件获取计数。
var TodoCount = React.createClass({
render: function() {
return (
<div> { this.props.count } </div>)
}
});
TodoHeader 组件显示应用程序的头,它调用 TodoCount 组件显示所有 items 的计数。
var TodoHeader = React.createClass({
render: function() {
return (
<nav>
Header
< TodoCount count = { this.props.count}
/>
</nav>
)
}
})
下面是 TodoForm 组件。 我们同样关注它是因为除了渲染之外它还要创建数据。
handleSubmit 方法在单击提交按钮时调用,它调用从 Application 组件获取的 Todo Submit 方法。
我当时有一些疑问:
-
为什么要用这个方法?
-
为什么 Application 组件提交表单而不是 TodoForm ?
原因是 Application 组件是所有组件的父/祖父组件。并且数据流是从父组件到子组件的并且子组件不能改变父组件的状态。此外,同级组件之间不能有任何通信数据流。
现在如果 TodoForm 要提交表单,那么这些信息要如何传递到 TodoList 或 TodoHeader 组件?
这就是为什么要让 Application 组件负责提交表单。
var TodoForm = React.createClass({
getInitialState: function() {
console.log("inside todo form of initial")
return { user: '', task: '' }
},
handleUserChange: function(e) {
this.setState({ user: e.target.value })
},
handleTaskChange: function(e) {
this.setState({ task: e.target.value })
},
handleSubmit: function(e) {
e.preventDefault();
this.props.onTodoSubmit({ user: this.state.user, task: this.state.task })
this.setState({ user: '', task: '' })
},
render: function() {
return (
<form className = "todoform" onSubmit = { this.handleSubmit } >
<input type = "text" placeholder = "your name"
value = { this.state.user } onChange = { this.handleUserChange } />
<input type = "text" placeholder = "your task"
value = { this.state.task }
onChange = { this.handleTaskChange } />
<input type = "submit" value = "submit" />
</form>
)
}
})
应用组件是所有组件的父组件。于是它涉及的方法需要讨论一下。
loadDataFromServer – 它会从服务器加载数据,但在例子中没有任何服务器,所以就将数据硬编码了。
handleTodoSubmit – 这个方法将由 TodoForm 调用,就像 TodoForm 组件中讲解的那要。。
当这个方法被调用时,它将随着新创建的 Todo item 改变状态,这个新的 Todo item 会触发Application 组件的重新渲染,并且所有子组件将随着新的信息而更新。
var TODO = React.createClass({
getInitialState: function() {
return { data: [] }
},
loadDataFromServer: function() {
this.setState({
data: [
{ id: 1, user: "Adam", task: "This is task1"},
{ id: 2, user: "Ricky",task: "This is task2"}
]
})
},
componentDidMount: function() {
this.loadDataFromServer()
},
handleTodoSubmit: function(todo) {
todo.id = Date.now()
var todos = this.state.data
var newTodos = todos.concat([todo])
this.setState({
data: newTodos
})
},
render: function() {
return (
<div className = "todo">
<TodoHeader count = { this.state.data.length } />
<TodoForm onTodoSubmit = { this.handleTodoSubmit } />
< TodoList data = { this.state.data } />
</div>
)
}
})
ReactDOM.render( < TODO /> , document.getElementById("example"))
可以看到,如果同级组件想要彼此通信,就需要将数据传递到它们的父组件。
像是例子中的 Todo Form 想告知 Todo List 有新的 item 被添加了。
这就是为什么 Application 组件传递回调方法 handleTodoSubmit。 所以在 Todo Form 提交 时它通过回调调用 Application 组件的 handleTodoSubmit 方法。 而 handleTodoSubmit 正在更新 Application 的状态,这使得通过更新 Todo Item 和 Todo Header 来重新渲染 Application 组件。
在例子中,只有1个层级,但在实时情况下,可能有多个层级,而最内层的子层想要更新其他层的最内层子层。 这就需要传递的回调方法覆盖所有层级。
但这会使其不易维护,也大大降低可读性,这也使 React 的优势大打折扣。
现在试试相同的应用使用 Flux
|
Store(存储)
|
结论
|
TodoList 组件显示 Todo Items 的列表,因此需要 TodoItems。在与 AppStore 通信方面,行为类似于 TodoCount 。 在 TodoForm 中,要提交表单并告知其他组件已经添加了新的item。所以在提交时,它只是传递信息到 AppAction 而不是告知其它组件,AppAction 会在AppDispatcher 的帮助下将其调度到 store 。而 AppStore 会更新/添加数据。 在 AppStore 中,有名为 emitChange 的发出信号的方法,它可以让监听器知道信息已更新/添加。 可见组件不彼此依赖。 如果它们需要任何信息,他们将从 Store 获取,如果他们想更新任何东西,那么他们将创建一个 Action,它会被调度到 Store。 |
本文标题:如何在使用 Flux 时使 ReactJS 更好地发挥作用
本文地址:https://www.oschina.net/translate/how-reactjs-is-even-more-powerful-if-you-use-flux-
参与翻译:startkknd
英文原文:How ReactJS is Even More Powerful if You Use Flux