你們週末好,2016年的最後幾篇文章開始寫到了React的一些東西,那麼最近就來一些圖表君對於React的簡單總結和理解,那麼今天就開始第一篇,說一說React的事件系統。javascript
簡單來講React實現了一個SyntheticEvent層,全部定義的事件處理器均可以接受到一個SyntheticEvent對象的實例,他是一個跨瀏覽器的對於原生事件的包裝,和原生事件同樣有一樣的接口,包括stopPropagation()和preventDefault()。java
在React中不會把全部的事件處理器綁定到相應的真實的DOM節點上,而是使用一個統一的事件監聽器,把全部的事件綁定在最外層。當事件發生的時候,首先被這個統一的事件監聽器處理,隨後找到真正的事件處理函數進行調用,這樣是爲了提升效率,這是由於在UI系統中,事件處理器越多,那麼佔據的內存就越大,React的作法是將其簡化爲一個,這樣就大大提升了效率。在以前開發者須要爲了優化性能須要本身來優化本身的事件處理器的代碼,如今React幫助你完成了這些工做。react
說了這麼許多理論上的知識,咱們來看看合成事件是怎麼使用的。瀏覽器
bind方法。app
咱們來直接看代碼函數
import React, {Component} from 'react'; class EventApp extends Component { handleClick(e,args){ console.log('this is the react event',e) console.log('this is the args', args) } render(){ return <button onClick={this.handleClick.bind(this,'test')}>Test</button> } }
構造器內聲明性能
再來看代碼
import React, {Component} from 'react'; class EventApp extends Component { constructor(props){ super(props); this.handleClick = this.handleClick.bind(this); } handleClick(e){ console.log('this is the react event',e) } render(){ return <button onClick={this.handleClick}>Test</button> } }
使用構造器內聲明的方法,僅僅要綁定一次而不須要每次使用的時候都綁定一次。優化
箭頭函數this
class ButtonApp extends React.Component { handleClick (e) { console.log(e.target.value) } render(){ return <button onClick={(e) => this.handleClick(e)}>Test</button>; } }
從上邊的使用方式咱們能夠看出React來使用合成事假仍是很簡單的,可是現實的世界老是更加的複雜的。那麼在React中咱們能夠使用原始事件嗎?固然是能夠的。code
在React中咱們也能夠使用原生事件,那麼如何進行綁定呢,由於React提供了ComponentDidMount這樣的API讓咱們能夠調用,那麼要使用原生事件咱們就能夠在DidMount後進行綁定。例如上邊的那個例子中若是咱們想把click事件綁定在原生button上該怎麼作呢?咱們來看代碼:
class ButtonApp extends React.Component { componentDidMount(){ this.refs.button.addEventListener('click' e => { console.log(e); }) } componentWillUnmount(){ this.refs.button.removeEventListener('click') } render(){ return <button ref="button">Test</button> } }
在這裏例子中咱們使用原生事件的方法綁到了button上,注意一點的是在DidMount上add了這個listener在willUnmont上remove這個listener。必定要手動的記住移除,否則可能會出現內存泄漏問題。若是咱們使用React合成事件,這些事React已經幫你作好了。可是現實的狀況下咱們有一些場景是不得不用到原生的事件的那麼該怎麼作呢?
咱們來看下邊的一個例子。例如咱們要實現這樣的一個功能,在頁面上有個button,當點擊它會出現一個圖片。當點擊頁面的其餘部分的時候,這個圖片會自動的消失,那麼這樣的需求咱們就不得不使用原生的事件了。話很少說咱們來看代碼實現。
import React from 'react'; class App extends React.Component { constructor(props){ super(props); this.state = { show: false } this.handleClick = this.handleClick.bind(this) this.handleClickImage = this.handleClickImage.bind(this); } handleClick(){ this.setState({ show: true }) } componentDidMount(){ document.body.addEventListener('click', e=> { this.setState({ show: false }) }) } componentWillUnmount(){ document.body.removeEventListener('click'); } render(){ return ( <div className="container"> <button onClick={this.handleClick}>Open Image</button> <div className="img-container" style={{ display: this.state.show ? 'block': 'none'}} > <img src="http://blog.addthiscdn.com/wp-content/uploads/2014/11/addthis-react-flux-javascript-scaling.png" /> </div> </div> ) } } ReactDOM.render(<App />, document.getElementById('root'));
上邊一個例子中,咱們實現了組件APP,他裏邊有一個button,它上邊有一個handleClick的事件處理器,當觸發時會把app的state裏show製成true,這樣圖片就顯示了出來。同時在body上使用了原生事件,當發生點擊事件的時候,就會被收起,這樣就簡單實現了需求的功能,那是看似這樣好像就沒有問題的,可是這其中有個bug,究竟是什麼問題呢,咱們下篇文章繼續。看看原生事件和合成事件混用的那些事。
參考文獻:深刻react技術棧