双向绑定辅助

ReactLink 是一个用React表达双向绑定的简单方法。

注意:

如果你刚学这个框架,注意 ReactLink 对大多数应用是不需要的,应该慎重的使用。

在React里,数据单向流动: 从拥有者到子级。这是因为数据只单向流动 the Von Neumann model of computing。你可以把它想象为 “单向数据绑定”。

然而,有很多应用需要你去读某些数据并回流他们到你的程序。例如,当开发forms,你会常常想更新一些React state 当你收到用户输入的时候。或者也许你想在JavaScript完成布局并相应一些DOM元素大小的变化。

在React里,你可以用监听 “change” 事件来实现它,从你的数据源(通常是DOM)读取并在你的某个组件调用 setState() 。明确的”Closing the data flow loop” 致使了更容易理解和维护的程序。更多信息见 our forms documentation.

双向绑定 — 隐含的强迫DOM里的某些值总是和某些React state 同步 — 简洁并支持大量多样的应用。 我们提供了 ReactLink:设置如上描述的通用数据回流模式的语法糖,或者 “linking” 某些数据结构到 React state.

注意:

ReactLink 只是一层对 onChange\/setState() 模式的薄包装。它没有根本性的改变你的React应用里数据如何流动。

这里有一个简单的 不用 ReactLink 的 form 例子:

  1. var NoLink = React.createClass({
  2. getInitialState: function() {
  3. return {message: 'Hello!'};
  4. },
  5. handleChange: function(event) {
  6. this.setState({message: event.target.value});
  7. },
  8. render: function() {
  9. var message = this.state.message;
  10. return <input type="text" value={message} onChange={this.handleChange} />;
  11. }
  12. });

这个工作的很好并且数据如何流动很清晰,然而,当有大量的 form fields时,可能会有些冗长。让我们使用 ReactLink 来节省我们的输入:

  1. var LinkedStateMixin = require('react-addons-linked-state-mixin');
  2. var WithLink = React.createClass({
  3. mixins: [LinkedStateMixin],
  4. getInitialState: function() {
  5. return {message: 'Hello!'};
  6. },
  7. render: function() {
  8. return <input type="text" valueLink={this.linkState('message')} />;
  9. }
  10. });

LinkedStateMixin 添加了一个 linkState() 方法到你的React组件。linkState() 返回一个 ReactLink 包含当前React state值的对象和一个改变它的回调函数。

ReactLink 对象可以作为props在树中上下传递,所以很容易(显示的)在深层次的组件和高层次的state之间 设置双向绑定。

注意 checkboxes 有一个关于他们 value 属性的特殊行为,这个行为是 如果checkbox被选中 值会在表单提交时被发送。 value 不会 checkbox 选中或是不选中时更新。对于checkboxes,你应该用checkedLink 代替 valueLink:

  1. <input type="checkbox" checkedLink={this.linkState('booleanValue')} />

引擎盖下

There are two sides to ReactLink: the place where you create the ReactLink instance and the place where you use it. To prove how simple ReactLink is, let’s rewrite each side separately to be more explicit.

  1. var WithoutMixin = React.createClass({
  2. getInitialState: function() {
  3. return {message: 'Hello!'};
  4. },
  5. handleChange: function(newValue) {
  6. this.setState({message: newValue});
  7. },
  8. render: function() {
  9. var valueLink = {
  10. value: this.state.message,
  11. requestChange: this.handleChange
  12. };
  13. return <input type="text" valueLink={valueLink} />;
  14. }
  15. });

As you can see, ReactLink objects are very simple objects that just have a value and requestChange prop. And LinkedStateMixin is similarly simple: it just populates those fields with a value from this.state and a callback that calls this.setState().

  1. var LinkedStateMixin = require('react-addons-linked-state-mixin');
  2. var WithoutLink = React.createClass({
  3. mixins: [LinkedStateMixin],
  4. getInitialState: function() {
  5. return {message: 'Hello!'};
  6. },
  7. render: function() {
  8. var valueLink = this.linkState('message');
  9. var handleChange = function(e) {
  10. valueLink.requestChange(e.target.value);
  11. };
  12. return <input type="text" value={valueLink.value} onChange={handleChange} />;
  13. }
  14. });

The valueLink prop is also quite simple. It simply handles the onChange event and calls this.props.valueLink.requestChange() and also uses this.props.valueLink.value instead of this.props.value. That’s it!