組件並非真實的 DOM 節點,而是存在於內存之中的一種數據結構,叫作虛擬 DOM (virtual DOM)。只有當它插入文檔之後,纔會變成真實的 DOM 。根據 React 的設計,全部的 DOM 變更,都先在虛擬 DOM上發生,而後再將實際發生變更的部分,反映在真實 DOM上,這種算法叫作 DOM diff ,它能夠極大提升網頁的性能表現。可是,有時須要從組件獲取真實 DOM 的節點,這時就要用到 React.findDOMNode 方法。javascript
var MyComponent = React.createClass({ handleClick: function() { React.findDOMNode(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> ); } }); React.render( <MyComponent />, document.getElementById('example') );
須要注意的是,因爲 React.findDOMNode 方法獲取的是真實 DOM ,因此必須等到虛擬 DOM 插入文檔之後,才能使用這個方法,不然會返回 null 。上面代碼中,經過爲組件指定 Click 事件的回調函數,確保了只有等到真實 DOM 發生 Click 事件以後,纔會調用 React.findDOMNode 方法。css
設置State的初始狀態。html
var MyComponent = React.createClass({ getInitialState: function(){ return { count: 5 } }, render: function(){ return ( <h1>{this.state.count}</h1> ) } });
參考資料java
React行內樣式最佳實踐react
在React中,若是要使用行內元素,不能夠直接使用style="」這種方式,能夠有:git
import React from 'react'; var style = { backgroundColor: '#EEE' }; export default React.createClass({ render: function () { return ( <div style={style}> //或者<div style={{backgroundColor: '#EEE'}}> <h1>Hello world</h1> </div> ) } });
能夠看出,React的style屬性接收的也是一個JavaScript對象。github
你能夠根據這個策略爲每一個組件建立 CSS 文件,可讓組件名和 CSS 中的 class 使用一個命名空間,來避免一個組件中的一些 class 干擾到另一些組件的 class。算法
app/components/MyComponent.cssapi
.MyComponent-wrapper { background-color: #EEE; }
app/components/MyComponent.jsx瀏覽器
import './MyComponent.css'; import React from 'react'; export default React.createClass({ render: function () { return ( <div className="MyComponent-wrapper"> <h1>Hello world</h1> </div> ) } });
上文中說起的利用className方式賦值,若是在存在多個類名的狀況下:
render: function() { var cx = React.addons.classSet; var classes = cx({ 'message': true, 'message-important': this.props.isImportant, 'message-read': this.props.isRead }); // same final string, but much cleaner return <div className={classes}>Great, I'll be there.</div>; }
React對於事件的支持很是完善,能夠查看這裏。React 實現了一個「合成事件」層(synthetic event system),這個事件模型保證了和 W3C 標準保持一致,因此不用擔憂有什麼詭異的用法,而且這個事件層消除了 IE 與 W3C 標準實現之間的兼容問題。「合成事件」額外提供了兩個好處:自動綁定上下文和事件委託
「合成事件」自動將事處理件方法的上下文綁到當前組件,因此 handleClick
方法裏面能夠直接使用this.setState
。
「合成事件」會以事件委託(event delegation)的方式綁定到組件最上層,而且在組件卸載(unmount)的時候自動銷燬綁定的事件。
固然,在React中,也可使用原生事件,好比你在 componentDidMount
方法裏面經過 addEventListener
綁定的事件就是瀏覽器原生事件。使用原生事件的時候注意在 componentWillUnmount
解除綁定 removeEventListener
。全部經過 JSX 這種方式綁定的事件都是綁定到「合成事件」,除非你有特別的理由,建議老是用 React 的方式處理事件。
最基本的綁定方式就是依靠相似於onClick={handleClick}
的方式,要注意,這裏不一樣於ng-click,onClick傳遞的參數只能是一個方法,而不能是一個調用。若是要簡單來寫的話能夠採Lambda表達式的方式:
onClick={()=>{alert(1);}}
給事件處理函數傳遞額外參數的方式:bind(this, arg1, arg2, ...)
render: function() { return <p onClick={this.handleClick.bind(this, 'extra param')}>; }, handleClick: function(param, event) { // handle click }
由上面能夠看出,Event通常都是做爲最後一個參數傳遞到handleClick中,這裏的event是SyntheticEvent對象,它的主要屬性以下:
boolean bubbles boolean cancelable DOMEventTarget currentTarget boolean defaultPrevented number eventPhase boolean isTrusted DOMEvent nativeEvent void preventDefault() void isDefaultPrevented() void stopPropagation() void isPropagationStopped() DOMEventTarget target number timeStamp string type
在React中,也會常常遇到須要爲某個羣組綁定事件的狀況,能夠參考以下代碼:
var GroceryList = React.createClass({ handleClick: function(i) { console.log('You clicked: ' + this.props.items[i]); }, render: function() { return ( <div> {this.props.items.map(function(item, i) { return ( <div onClick={this.handleClick.bind(this, i)} key={i}>{item}</div> ); }, this)} </div> ); } }); React.render( <GroceryList items={['Apple', 'Banana', 'Cranberry']} />, mountNode );
If you'd like to use React on a touch device such as a phone or tablet, simply call React.initializeTouchEvents(true);
to enable touch event handling.
譬如在某個子組件中,提供了某個方法:
var ButtonComponent = React.createClass({ getDragonKillingSword: function(){ //送寶刀 }, render: function(){ return (<button onClick={this.getDragonKillingSword}>屠龍寶刀,點擊就送</button>); } });
若是在父組件中想手動調用該方法,則能夠利用ref方式:
var ImDaddyComponent = React.createClass({ render: function(){ return ( <div> //其餘組件 <ButtonComponent /> //其餘組件 </div> ); } });
在父組件的功能方程中:
this.refs.getSwordButton.getDragonKillingSword();
反之,若是須要在子組件中調用父組件的方法,則能夠直接將父組件的方法做爲Props參數傳入到子組件中:
<ButtonComponent clickCallback={this.getSwordButtonClickCallback}/>
組件的數據來源,一般是經過 Ajax 請求從服務器獲取,能夠在componentDidMount 方法中設置 Ajax 請求,等到請求成功,再用 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> ); } }); React.render( <UserGist source="https://api.github.com/users/octocat/gists" />, document.body );
不過筆者習慣仍是將整個獲取數據,處理數據的業務邏輯放在Angular中進行。