NO.7獲取真實(shí)的DOM
組件其實(shí)只是存在內(nèi)存中的一種數(shù)據(jù)結(jié)構(gòu)会涎,叫做虛擬DOM(virtual DOM)耕拷,只有插入文檔以后,才變成真實(shí)的DOM,據(jù) React 的設(shè)計(jì)俊卤,所有的 DOM 變動(dòng)嫩挤,都先在虛擬 DOM 上發(fā)生,然后再將實(shí)際發(fā)生變動(dòng)的部分消恍,反映在真實(shí) DOM上岂昭,這種算法叫做 DOM diff ,它可以極大提高網(wǎng)頁(yè)的性能表現(xiàn)狠怨。
假設(shè)有一個(gè)名為Name的組件约啊,組件代碼如下:
class Name extends React.Component {
render () {
return (
<div>
<input type="text"/>
<input type="button" value="Focus the text input" />
</div>
);
}
}
這個(gè)組件渲染出來(lái)的視圖為一個(gè)輸入框和一個(gè)按鈕邑遏。如果想要拿到用戶輸入的數(shù)據(jù),就必須獲取真實(shí)DOM的節(jié)點(diǎn)恰矩,所以记盒,需要給輸入框加入ref屬性。然后this.refs.[refName]就能獲取到真實(shí)的DOM節(jié)點(diǎn)外傅。
另外值得注意的是纪吮,想要獲取真實(shí)DOM,必須等虛擬DOM插入到文檔之后萎胰,才能成功獲取碾盟,所以this.refs.[refName]方法必須確保真實(shí)DOM存在后再使用,所以為組件指定click回調(diào)函數(shù)技竟。代碼改為如下:
class Name extends React.Component {
render (){
return (
<div>
<input type="text" ref="myTextInput" />
<input type="button" value="Focus the text input" onClick={this.handleClick} />
</div>
);
}
handleClick(){
let va = this.refs.myTextInput.value;
console.log(va);
}
}
根據(jù)ES6語(yǔ)法冰肴,變量命名需要加上let,否則會(huì)報(bào)錯(cuò)。
運(yùn)行代碼榔组,點(diǎn)擊按鈕獲取輸入框的值熙尉,仍然報(bào)錯(cuò)
Uncaught TypeError: Cannot read property 'refs'。
原因是onClick={this.handleClick}需要加入bind(this),改為onClick={this.handleClick.bind(this)}
,現(xiàn)在就能成功獲取輸入框里的值了瓷患。
NO.8 狀態(tài)(this.state)
組件的狀態(tài)骡尽,用來(lái)和用戶互動(dòng),組件一開(kāi)始有一個(gè)狀態(tài)擅编,然后用戶操作導(dǎo)致?tīng)顟B(tài)改變攀细,從而改變狀態(tài),根據(jù)狀態(tài)重新渲染頁(yè)面爱态。
class Name extends React.Component {
constructor(props) {
super(props);
this.state = {liked: false};
}
render () {
let text = this.state.liked? "喜歡" : "不喜歡";
return (
<div>
<input type="text" ref="myTextInput" />
<input type="button" value={text} onClick={this.handleClick.bind(this)} />
</div>
);
}
handleClick(){
let va = this.refs.myTextInput.value;
this.setState({liked: !this.state.liked});
console.log(va);
}
}
以上就是根據(jù)用戶的操作改變當(dāng)前組件的狀態(tài)谭贪,根據(jù)用戶點(diǎn)擊按鈕,交替顯示喜歡還是不喜歡锦担。相當(dāng)于一個(gè)點(diǎn)贊按鈕俭识。
ES6寫法,初始化組件的狀態(tài)
constructor(props) {
super(props);
this.state = {liked: false};
}
將組件狀態(tài)設(shè)置為當(dāng)前狀態(tài)相反狀態(tài)
this.setState({liked: !this.state.liked});
NO9.表單
文本輸入框的值洞渔,不能用 this.props.value 讀取套媚,而要定義一個(gè) onChange 事件的回調(diào)函數(shù),通過(guò) event.target.value 讀取用戶輸入的值磁椒。textarea 元素堤瘤、select元素、radio元素都屬于這種情況浆熔。
'use strict';
import React from "react";
class Input extends React.Component {
constructor(props) {
super(props);
this.state = {value : "hello"};
}
render () {
let value = this.state.value;
return (
<div>
<input type="text" value={value} onChange={this.handleChange.bind(this)} />
</div>
)
}
handleChange(event){
this.setState({value: event.target.value});
let a = this.state.value
console.log(a);
}
}
export { Input as default };
如上代碼本辐,input里面的value只能用過(guò)onChange={this.handleChange.bind(this)}
這個(gè)方法來(lái)獲得,將value和狀態(tài)綁定在一起,當(dāng)輸入框改變時(shí)慎皱,改變組件狀態(tài)老虫,將value存入狀態(tài)中,讀取輸入框的數(shù)據(jù)時(shí)茫多,只能讀取狀態(tài)里的value祈匙。
NO.10 組件的生命周期
組件的生命周期有三個(gè)狀態(tài):
- Mounting:已插入真實(shí) DOM
- Updating:正在被重新渲染
- Unmounting:已移出真實(shí) DOM
React為每個(gè)狀態(tài)提供了兩種處理函數(shù),will在進(jìn)入狀態(tài)之前用地梨,did在進(jìn)入狀態(tài)之后調(diào)用菊卷。
- componentWillMount()
- componentDidMount()
- componentWillUpdate(object nextProps, object nextState)
- componentDidUpdate(object prevProps, object prevState)
- componentWillUnmount()
下面一段實(shí)例代碼來(lái)說(shuō)明生命周期:
'use strict';
import React from "react";
class Input extends React.Component {
constructor(props) {
super(props);
this.state = {opacity : 1.0};
}
componentDidMount() {
this.timer = setInterval(function () {
var opacity = this.state.opacity;
opacity -= .05;
if (opacity < 0.1) {
opacity = 1.0;
}
this.setState({
opacity: opacity
});
}.bind(this), 100);
}
render () {
let value = this.state.value;
return (
<div>
<input type="text" style={{opacity: this.state.opacity}} />
</div>
)
}
}
export { Input as default };
componentDidMount方法在已經(jīng)插入真實(shí)DOM后之后,每100ms修改input框的透明度宝剖,當(dāng)透明度被修改的時(shí)候洁闰,狀態(tài)對(duì)應(yīng)修改,又需要重新
渲染DOM万细,會(huì)產(chǎn)生輸入框一直輸入的效果扑眉。
注意的是:style={% raw %}{{opacity: this.state.opacity}}{% endraw %}
應(yīng)該寫成這樣,這是因?yàn)?React 組件樣式是一個(gè)對(duì)象赖钞。
NO.11 Ajax
組件的數(shù)據(jù)來(lái)源腰素,通常是通過(guò) Ajax 請(qǐng)求從服務(wù)器獲取,可以使用 componentDidMount 方法設(shè)置 Ajax 請(qǐng)求雪营,等到請(qǐng)求成功弓千,再用 this.setState 方法重新渲染 UI
var UserGist = React.createClass({
getInitialState: function() {
return {
username: '',
lastGistUrl: ''
};
},
componentDidMount: function() {
$.get(this.props.source, function(result) {
var lastGist = result[0];
if (this.isMounted()) {
this.setState({
username: lastGist.owner.login,
lastGistUrl: lastGist.html_url
});
}
}.bind(this));
},
render: function() {
return (
<div>
{this.state.username}'s last gist is
<a href={this.state.lastGistUrl}>here</a>.
</div>
);
}
});
ReactDOM.render(
<UserGist source="https://api.github.com/users/octocat/gists" />,
document.body
);
(完)
參考資料:React 入門實(shí)例教程(阮一峰)