Description
在任何应用中管理数据都是必不可少的。通过用户界面来编排数据流是一项具有挑战的工程。现代的 Web 应用会涉及复杂的 UI 交互,比如改变了一个地方的 UI 数据,需要直接或者间接的改变其他地方的 UI 数据。一些双向绑定的框架(比如:Angular.js 等)都是对这种场景比较好的解决方案。
对于一些应用(尤其是数据流比较简单的),这种双向绑定是非常快速和足够的解决方案。但是对于一些更加复杂的应用场景,数据双向绑定已经被证明是不够的,它会妨碍用户界面的设计。实际上,React 并没有解决这样一个复杂应用中比较复杂的数据流问题(虽然后面出现了 Flux 这种解决方案),但是他确实解决了一个组件中数据流的问题。
对于一个有上下文关系的组件, React 解决了数据流问题 —— 即通过更新 UI 来反应数据流的结果;除此之外,React 解决的另外一个问题是命名模式问题 —— 通过比较有创意的虚拟 DOM 解决。
组件数据的类型
在 React 中组件的数据存储在 props
和 state
中。
props
是一个组件的输入。他经常被用作渲染组件和初始化状态。当实例化完一个组件,props
应该是不可变的(持久的)。props
被用作在实例化组件的时候,然后组件将再次渲染 DOM,在这个过程中,React 将会对比新 props
和老 props
然后来确定哪些 DOM 的变化是必要的。
下面是一个设置 props
然后用 props
的变化来更新 DOM 的例子:
"use strict";
var HelloWorld = React.createClass({
render: function() {
return (
<div>
<span>Counter: {this.props.count}</span>
<br />
<input type="text" />
</div>
);
},
});
var
mainElement = document.querySelector("main"),
count = 1;
setInterval(function() {
ReactDOM.render(<HelloWorld count={count++}></HelloWorld>, mainElement);
http://codepen.io/SitePoint/pen/XKqQqN
state
可以通过组组件发生变化,这种变化经常会和组件的事件处理函数连接起来。通常情况下,state
的这种变化会触发组件的重新渲染。在组件初始化之前,他的 state
必须先进行初始化,其值包含常数、props
。
与 Angular 这样的框架相比,可以理解为 props
是单向数据绑定,state
是双向数据绑定。当然这并不是一种恰当的比喻: Angular 使用一种有两种方式的数据对象,而 React 是使用两种数据对象,每种对象都有着自己的使用方法。
Props
当我们给一个组件添加 css
样式的 class
时,我们必须用 className
,而不是 class
。这是因为在 ES 2015 中 class
是一个用来定义对象的保留字。为了去避免这种冲突,在 React 中使用了 className
。如果你使用了 class
,React 将会在 console 里面输出一段友好的提示,让你使用 className
而不是 class
。
除了像 className
一样这些 props
的名字之外,props
还有一些其他有意思的地方。比如改变 props 的值就是一种反模式。props
应该在组件实例化之前就进行设置,在这之后进行设置是不可的。其中就包括在组件实例化之后(render 之后)。可变值在组件中被认为是状态,一般使用 state
而不是 props
。
在下面的这个例子中,someComponent
实例化了,在这之后 props
的值发生了变化。
var someComponent = <SomeComponent />;
someComponent.props.prop1 = “some value”;
someComponent.props.prop2 = “some value”;
改变 props
的值会让应用程序发生一些错误,并且这种错误是无法跟踪的。于此同时,改变 props
的值不会触发组件的再次渲染,这样就会让数据和界面不是同步的。
所以。props
应该在实例化的时候作为组件的一部分。
var someComponent = <SomeComponent prop1=”some value” prop2=”some value” />
这样,props
发生变化的时候就会协调进行 DOM 树的对比,然后进行 UI 的更新。
State
state
表示组件内可变的状态,这个状态一般是由用户去作用而产生的。为了促成这种改变,事件处理程序将会作用在相应的 DOM 元素上,当事件触发之后,值将会从 DOM 上取得,然后去通知组件有一个新的 state
。在组件使用 state
之前,state
必须通过 getInitialState
函数进行初始化。通常情况下,getInitilaState
函数通过静态值、props
或者其他数据源进行初始化 state
。
var Message = React.createClass({
getInitialState: function() {
return { message: this.props.message };
},
一旦 state
被初始化,就能像 props
一样在组件中使用了。为了去捕获用户的行为带来,然后去更新 state
,各种需要使用的事件函数都会注册。为了保持组件的独立(和其他组件之间只通过数据进行交换,较少耦合性),每个事件处理函数都可以以 props
的形式进性传递,也可以直接在组件内进行定义。
"use strict";
var Message = React.createClass({
getInitialState: function() {
return { message: this.props.message };
},
_messageChange: function(e) {
this.setState({ message: e.target.value });
},
render: function() {
return (
<div>
<span>Message: {this.state.message}</span>
<br />
Message: <input type="text" value={this.state.message} onChange={this._messageChange} />
</div>
);
},
});
var mainElement = document.querySelector("main");
ReactDOM.render(<Message message="Hello World!!" />, mainElement);
React 的另外一个优点就是使用了标准的 HTML 事件。这样一来学习特殊的事件库,事件处理函数和第三方事件就不再是需要的。
为了去处理 state
的变化,setState
函数被用来设置 state
的新值。调用这个函数会触发组件的重新渲染。
结论
React 组件对数据提供了两种机制: props
与 state
。他把数据清楚的划分为了持久性数据 props
与经常改变的数据 state
,然后把这两种数据和组件产生关联。
通常意义上,对于简单的数据流 props
是首选的,state
对于捕获用户交互或者其他 UI 事件造成的数据更新是非常有用的。
props
和 state
之间的关系促成了数据通过组件的流动。props
可以用来初始化 state
,state
可以在初始化、渲染组件的使用设置 props
。通过 state
来捕获用户输出的值、更新 props
。
上面讨论的只是组件中数据流相关,对于大型的应用中的数据流建议使用 Flux
等
原文:https://www.sitepoint.com/working-with-data-in-react-properties-state/
版权声明
- 请尊重辛勤劳动
- 禁止不署名完全转载,可单独通过下面的捐赠付版权费
- 建议署名并进行摘要性质转载
捐赠
写文不易,赠我一杯咖啡增强一下感情可好?