`ReactLink`是一種簡單表達React雙向綁定的方式。
> 注意:
>
> 如果你是這個框架的初學者,記住`ReactLink`對于大多數應用來說都是不需要的,應該謹慎使用。
在React里面,數據流是一個方向的:從擁有者到子節點。這是因為根據[the Von Neumann model of computing](http://en.wikipedia.org/wiki/Von_Neumann_architecture),數據僅向一個方向傳遞。你可以認為它是`單向數據綁定`。
然而,有很多應用需要你讀取一些數據,然后傳回給你的程序。例如,在開發表單的時候,當你接收到用戶輸入時,你將會頻繁地想更新某些React?`state`。或者你想在JavaScript中演算布局,然后反應到某些DOM元素的尺寸上。
在React中,你可以通過監聽一個“change”事件來實現這個功能,從你的數據源(通常是DOM)讀取,然后在你某個組件上調用`setState()`。"關閉數據流循環"明顯會引導寫出更加容易理解的和維護的程序。查看[我們的表單文檔](http://reactjs.cn/react/docs/forms.html)來獲取更多信息。
雙向綁定 -- 隱式地強制在DOM里面的數據總是和某些React?`state`保持一致 -- 是簡明的,并且支持非常多的應用。我們已經提供了`ReactLink`:如上所述,是一種設置通用數據流循環模型的語法糖,或者說“關聯”某些數據到React?`state`。
> 注意:
>
> ReactLink僅僅是一個`onChange`/`setState()`模式的簡單包裝和約定。它不會從根本上改變數據在你的React應用中如何流動。
## ReactLink: 前后對比
這是一個簡單的表單示例,沒有使用`ReactLink`:
~~~
var NoLink = React.createClass({
getInitialState: function() {
return {message: 'Hello!'};
},
handleChange: function(event) {
this.setState({message: event.target.value});
},
render: function() {
var message = this.state.message;
return <input type="text" value={message} onChange={this.handleChange} />;
}
});
~~~
這段代碼運行地很好,數據如何流動是非常清晰的,但是,如果表單有大量的字段,代碼就會很冗長了。讓我們使用`ReactLink`來減少打字輸入:
~~~
var WithLink = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {message: 'Hello!'};
},
render: function() {
return <input type="text" valueLink={this.linkState('message')} />;
}
});
~~~
`LinkedStateMixin`給你的React組件添加一個叫做`linkState()`的方法。`linkState()`返回一個`ReactLink`對象,包含React state當前的值和一個用來改變它的回調函數。
`ReactLink`對象可以在樹中作為props被向上傳遞或者向下傳遞,so it's easy (and explicit) to set up two-way binding between a component deep in the hierarchy and state that lives higher in the hierarchy.
注意,對于checkbox的`value`屬性,有一個特殊的行為,如果checkbox被選中(默認是`on`),`value`屬性值將會在表單提交的時候發送出去。當checkbox被選中或者取消選中的時候,`value`屬性是不會更新的。對于checkbox,你應該使用`checkLink`而不是`valueLink`:
~~~
<input type="checkbox" checkedLink={this.linkState('booleanValue')} />
~~~
## 底層原理(Under the Hood)
對于`ReactLink`,有兩塊兒:你創建`ReactLink`實例的地方和你使用它的地方。為了證明`ReactLink`是多么的簡單,讓我們單獨地重寫每一塊兒,以便顯得更加明了。
### 不帶ReactLink的LinkedStateMixin(ReactLink Without LinkedStateMixin)
~~~
var WithoutMixin = React.createClass({
getInitialState: function() {
return {message: 'Hello!'};
},
handleChange: function(newValue) {
this.setState({message: newValue});
},
render: function() {
var valueLink = {
value: this.state.message,
requestChange: this.handleChange
};
return <input type="text" valueLink={valueLink} />;
}
});
~~~
如你所見,`ReactLink`對象是非常簡單的,僅僅有一個`value`和`requestChange`屬性。`LinkedStateMixin`也同樣簡單:它僅占據這些字段,用來自于`this.state`的值和一個調用`this.setState()`的回調函數。(And?`LinkedStateMixin`?is similarly simple: it just populates those fields with a value from?`this.state`?and a callback that calls`this.setState()`.)
### 不帶valueLink的ReactLink(ReactLink Without valueLink)
~~~
var WithoutLink = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {message: 'Hello!'};
},
render: function() {
var valueLink = this.linkState('message');
var handleChange = function(e) {
valueLink.requestChange(e.target.value);
};
return <input type="text" value={valueLink.value} onChange={handleChange} />;
}
});
~~~
`valueLink`屬性也很簡單。它簡單地處理`onChange`事件,然后調用`this.props.valueLink.requestChange()`,同時也用`this.props.valueLink.value`替換`this.props.value`。就這么簡單!