React提供了強大的抽象,讓你在大多數(shù)應用場景中不再直接操作DOM,但是有時你需要簡單地調(diào)用底層的API,或者借助于第三方庫或已有的代碼。
React是很快的,因為它從不直接操作DOM。React在內(nèi)存中維護一個快速響應的DOM描述。render()
方法返回一個DOM的描述,React能夠利用內(nèi)存中的描述來快速地計算出差異,然后更新瀏覽器中的DOM。
另外,React實現(xiàn)了一個完備的虛擬事件系統(tǒng),盡管各個瀏覽器都有自己的怪異行為,React確保所有事件對象都符合W3C規(guī)范,并且持續(xù)冒泡,用一種高性能的方式跨瀏覽器(and everything bubbles consistently and in a performant way cross-browser)。你甚至可以在IE8中使用一些HTML5的事件!
大多數(shù)時候你應該呆在React的“虛擬瀏覽器”世界里面,因為它性能更加好,并且容易思考。但是,有時你簡單地需要調(diào)用底層的API,或許借助于第三方的類似于jQuery插件這種庫。React為你提供了直接使用底層DOM API的途徑。
為了和瀏覽器交互,你將需要對DOM節(jié)點的引用。每一個掛載的React組件有一個getDOMNode()
方法,你可以調(diào)用這個方法來獲取對該節(jié)點的引用。
注意:
getDOMNode()
僅在掛載的組件上有效(也就是說,組件已經(jīng)被放進了DOM中)。如果你嘗試在一個未被掛載的組件上調(diào)用這個函數(shù)(例如在創(chuàng)建組件的render()
函數(shù)中調(diào)用getDOMNode()
),將會拋出異常。
為了獲取一個到React組件的引用,你可以使用this
來得到當前的React組件,或者你可以使用refs來指向一個你擁有的組件。它們像這樣工作:
var MyComponent = React.createClass({ handleClick: function() { // Explicitly focus the text input using the raw DOM API. this.refs.myTextInput.getDOMNode().focus(); }, render: function() { // The ref attribute adds a reference to the component to // this.refs when the component is mounted. 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') );
為了學習更多有關(guān)Refs的內(nèi)容,包括如何有效地使用它們,參考我們的更多關(guān)于Refs文檔。
組件的生命周期包含三個主要部分:
掛載: 組件被插入到DOM中。
更新: 組件被重新渲染,查明DOM是否應該刷新。
移除: 組件從DOM中移除。
React提供生命周期方法,你可以在這些方法中放入自己的代碼。我們提供will方法,會在某些行為發(fā)生之前調(diào)用,和did方法,會在某些行為發(fā)生之后調(diào)用。
getInitialState(): object
在組件被掛載之前調(diào)用。狀態(tài)化的組件應該實現(xiàn)這個方法,返回初始的state數(shù)據(jù)。
componentWillMount()
在掛載發(fā)生之前立即被調(diào)用。
componentDidMount()
在掛載結(jié)束之后馬上被調(diào)用。需要DOM節(jié)點的初始化操作應該放在這里。
componentWillReceiveProps(object nextProps)
當一個掛載的組件接收到新的props的時候被調(diào)用。該方法應該用于比較this.props
和nextProps
,然后使用this.setState()
來改變state。
shouldComponentUpdate(object nextProps, object nextState): boolean
當組件做出是否要更新DOM的決定的時候被調(diào)用。實現(xiàn)該函數(shù),優(yōu)化this.props
和nextProps
,以及this.state
和nextState
的比較,如果不需要React更新DOM,則返回false。
componentWillUpdate(object nextProps, object nextState)
在更新發(fā)生之前被調(diào)用。你可以在這里調(diào)用this.setState()
。
componentDidUpdate(object prevProps, object prevState)
在更新發(fā)生之后調(diào)用。
componentWillUnmount()
在組件移除和銷毀之前被調(diào)用。清理工作應該放在這里。
_掛載的_復合組件也支持如下方法:
getDOMNode(): DOMElement
可以在任何掛載的組件上面調(diào)用,用于獲取一個指向它的渲染DOM節(jié)點的引用。
forceUpdate()
當你知道一些很深的組件state已經(jīng)改變了的時候,可以在該組件上面調(diào)用,而不是使用this.setState()
。
在 Facebook,我們支持老版本的瀏覽器,包括 IE8。我們已經(jīng)擁有適當?shù)?polyfills 很長一段時間了,能夠允許我們寫有遠見的 JS。這意味著在我們的代碼庫中沒有黑客,我們?nèi)匀豢梢云诖覀兊拇a“工作”。例如,不用寫 +new Date()
,我們可以只寫 Date.now()
。由于開源的 React 和我們內(nèi)部使用的是一樣的,所以我們采取了使用超前思維 JS 的這種理念。
除了那種理念,我們也確立了我們的立場,作為一個 JS 庫的作者,不應該把 polyfills 作為庫的一部分 shipping。如果每個庫都這么做,很有可能你會多次發(fā)送相同的 polyfill,這可能相當于一部分無用代碼。如果你的產(chǎn)品需要支持老版本的瀏覽器,很有可能你已經(jīng)在使用類似 es5-shim 的東西了。
來自 kriskowal's es5-shim 的 es5-shim.js
提供了 React 所需的如下方法:
Array.isArray
Array.prototype.every
Array.prototype.forEach
Array.prototype.indexOf
Array.prototype.map
Date.now
Function.prototype.bind
Object.keys
String.prototype.split
String.prototype.trim
es5-sham.js
,同樣來自 kriskowal's es5-shim,提供了 React 所需的如下方法:
Object.create
Object.freeze
React 的 unminified 構(gòu)建需要來自 paulmillr's console-polyfill 的如下方法:
console.*
當使用 IE8 中的 HTML5 元素時,包括 <section>
,<article>
, <nav>
,<header>
和<footer>
,包含 html5shiv 或類似的一個腳本也是必須的。
雖然 React 非常擅長抽象瀏覽器的差異,但是一些瀏覽器是有限制的或呈現(xiàn)出怪異的行為,對于這種行為我們不能找到解決方案。
在 IE8 中,onScroll
事件并不 buddle,并且 IE8 沒有一個 API 定義處理程序來捕獲一個事件的階段,這意味著 React 沒有辦法監(jiān)聽這些事件。目前在 IE8 中,事件處理程序被忽略了。
更多信息請看 onScroll 在 IE8 中不起作用的 GitHub 問題。
更多建議: