React 起源于 Facebook 的內(nèi)部項目朵夏,因為該公司對市場上所有 JavaScript MVC 框架,都不滿意兰珍,就決定自己寫一套侍郭,用來架設(shè) Instagram 的網(wǎng)站。做出來以后掠河,發(fā)現(xiàn)這套東西很好用亮元,就在2013年5月開源了。
由于 React 的設(shè)計思想極其獨特唠摹,屬于革命性創(chuàng)新爆捞,性能出眾,代碼邏輯卻非常簡單勾拉。所以煮甥,越來越多的人開始關(guān)注和使用,認為它可能是將來 Web 開發(fā)的主流工具藕赞。
一成肘、獲取真實的DOM節(jié)點
組件并不是真實的 DOM 節(jié)點,而是存在于內(nèi)存之中的一種數(shù)據(jù)結(jié)構(gòu)斧蜕,叫做虛擬 DOM (virtual DOM)双霍。只有當它插入文檔以后,才會變成真實的 DOM 。根據(jù) React 的設(shè)計洒闸,所有的 DOM 變動染坯,都先在虛擬 DOM 上發(fā)生,然后再將實際發(fā)生變動的部分丘逸,反映在真實 DOM上单鹿,這種算法叫做 DOM diff ,它可以極大提高網(wǎng)頁的性能表現(xiàn)深纲。但是仲锄,有時需要從組件獲取真實 DOM 的節(jié)點,這時就要用到 ref屬性囤萤。示例代碼如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../build/react.js"></script>
<script src="../build/react-dom.js"></script>
<script src="../build/browser.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
var MyComponent = React.createClass({
handleClick: function() {
this.refs.myTextInput.focus();
},
render: function() {
return (
<div>
<input type="text" ref="myTextInput" />
<input type="button" value="請輸入" onClick={this.handleClick} />
</div>
);
}
});
ReactDOM.render(
<MyComponent />,
document.getElementById('example')
);
</script>
</body>
</html>
代碼運行結(jié)果如下:
部分代碼如下:
var MyComponent = React.createClass({
handleClick: function() {
this.refs.myTextInput.focus();
},
render: function() {
return (
<div>
<input type="text" ref="myTextInput" />
<input type="button" value="Focus the text input" onClick={this.handleClick} />
</div>
);
}
});
ReactDOM.render(
<MyComponent />,
document.getElementById('example')
);
上面代碼中昼窗,組件 MyComponent 的子節(jié)點有一個文本輸入框是趴,用于獲取用戶的輸入涛舍。這時就必須獲取真實的 DOM 節(jié)點,虛擬 DOM 是拿不到用戶輸入的唆途。為了做到這一點富雅,文本輸入框必須有一個ref屬性,然后 this.refs.[refName]就會返回這個真實的 DOM 節(jié)點肛搬。
需要注意的是没佑,由于 this.refs.[refName]屬性獲取的是真實 DOM ,所以必須等到虛擬 DOM 插入文檔以后温赔,才能使用這個屬性蛤奢,否則會報錯。上面代碼中陶贼,通過為組件指定 Click 事件的回調(diào)函數(shù)啤贩,確保了只有等到真實 DOM 發(fā)生 Click 事件之后,才會讀取 this.refs.[refName]屬性拜秧。
React 組件支持很多事件痹屹,除了 Click事件以外,還有 KeyDown 枉氮、Copy
志衍、Scroll等,完整的事件清單請查看官方文檔聊替。
二楼肪、this.state
組件免不了要與用戶互動,React 的一大創(chuàng)新惹悄,就是將組件看成是一個狀態(tài)機春叫,一開始有一個初始狀態(tài),然后用戶互動,導致狀態(tài)變化象缀,從而觸發(fā)重新渲染 UI 蔬将。示例代碼如下:
<!DOCTYPE html>
<html>
<head>
<script src="../build/react.js"></script>
<script src="../build/react-dom.js"></script>
<script src="../build/browser.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
var LikeButton = React.createClass({
getInitialState: function() {
return {liked: false};
},
handleClick: function(event) {
this.setState({liked: !this.state.liked});
},
render: function() {
var text = this.state.liked ? 'like' : 'haven\'t liked';
return (
<p onClick={this.handleClick}>
You {text} this. Click to toggle.
</p>
);
}
});
ReactDOM.render(
<LikeButton />,
document.getElementById('example')
);
</script>
</body>
</html>
代碼運行結(jié)果如下:
部分代碼如下:
var LikeButton = React.createClass({
getInitialState: function() {
return {liked: false};
},
handleClick: function(event) {
this.setState({liked: !this.state.liked});
},
render: function() {
var text = this.state.liked ? 'like' : 'haven\'t liked';
return (
<p onClick={this.handleClick}>
You {text} this. Click to toggle.
</p>
);
}
});
ReactDOM.render(
<LikeButton />,
document.getElementById('example')
);
上面代碼是一個 LikeButton 組件,它的 getInitialState 方法用于定義初始狀態(tài)央星,也就是一個對象霞怀,這個對象可以通過 this.state 屬性讀取。當用戶點擊組件莉给,導致狀態(tài)變化毙石,this.setState 方法就修改狀態(tài)值,每次修改以后颓遏,自動調(diào)用 this.render 方法徐矩,再次渲染組件。
由于 this.props 和 this.state 都用于描述組件的特性叁幢,可能會產(chǎn)生混淆滤灯。一個簡單的區(qū)分方法是,this.props 表示那些一旦定義曼玩,就不再改變的特性鳞骤,而 this.state 是會隨著用戶互動而產(chǎn)生變化的特性。
三黍判、表單
用戶在表單填入的內(nèi)容豫尽,屬于用戶跟組件的互動,所以不能用 this.props 讀取顷帖。示例代碼如下:
<!DOCTYPE html>
<html>
<head>
<script src="../build/react.js"></script>
<script src="../build/react-dom.js"></script>
<script src="../build/browser.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
var Input = React.createClass({
getInitialState: function() {
return {value: 'Hello!'};
},
handleChange: function(event) {
this.setState({value: event.target.value});
},
render: function () {
var value = this.state.value;
return (
<div>
<input type="text" value={value} onChange={this.handleChange} />
<p>{value}</p>
</div>
);
}
});
ReactDOM.render(<Input/>, document.getElementById('example'));
</script>
</body>
</html>
代碼運行結(jié)果如下:
部分代碼如下:
var Input = React.createClass({
getInitialState: function() {
return {value: 'Hello!'};
},
handleChange: function(event) {
this.setState({value: event.target.value});
},
render: function () {
var value = this.state.value;
return (
<div>
<input type="text" value={value} onChange={this.handleChange} />
<p>{value}</p>
</div>
);
}
});
ReactDOM.render(<Input/>, document.body);
上面代碼中美旧,文本輸入框的值,不能用 this.props.value讀取贬墩,而要定義一個 onChange事件的回調(diào)函數(shù)榴嗅,通過event.target.value讀取用戶輸入的值。textarea元素震糖、select元素录肯、radio元素都屬于這種情況,更多介紹請參考官方文檔吊说。