淺析React之事件系統(tǒng)(一)

大家周末好,2016年的最后幾篇文章開始寫到了React的一些東西,那么最近就來一些圖表君對于React的簡單總結(jié)和理解,那么今天就開始第一篇,說一說React的事件系統(tǒng)。

總覽

簡單來說React實現(xiàn)了一個SyntheticEvent層,所有定義的事件處理器都可以接受到一個SyntheticEvent對象的實例,他是一個跨瀏覽器的對于原生事件的包裝,和原生事件一樣有同樣的接口,包括stopPropagation()和preventDefault()。

合成事件的使用方式

在React中不會把所有的事件處理器綁定到相應(yīng)的真實的DOM節(jié)點上,而是使用一個統(tǒng)一的事件監(jiān)聽器,把所有的事件綁定在最外層。當(dāng)事件發(fā)生的時候,首先被這個統(tǒng)一的事件監(jiān)聽器處理,隨后找到真正的事件處理函數(shù)進行調(diào)用,這樣是為了提高效率,這是因為在UI系統(tǒng)中,事件處理器越多,那么占據(jù)的內(nèi)存就越大,React的做法是將其簡化為一個,這樣就大大提高了效率。在之前開發(fā)者需要為了優(yōu)化性能需要自己來優(yōu)化自己的事件處理器的代碼,現(xiàn)在React幫助你完成了這些工作。

合成事件的綁定方式

說了這么許多理論上的知識,我們來看看合成事件是怎么使用的。

  1. bind方法。

    我們來直接看代碼

    
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>
    }
        
}
        
    
  1. 構(gòu)造器內(nèi)聲明

    再來看代碼


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>
        }
        
 }

使用構(gòu)造器內(nèi)聲明的方法,僅僅要綁定一次而不需要每次使用的時候都綁定一次。

  1. 箭頭函數(shù)
class ButtonApp extends React.Component {

    handleClick (e) {
        console.log(e.target.value)
    }
 
    render(){
        return <button onClick={(e) => this.handleClick(e)}>Test</button>;
        }
    }
    

從上邊的使用方式我們可以看出React來使用合成事假還是很簡單的,但是現(xiàn)實的世界總是更加的復(fù)雜的。那么在React中我們可以使用原始事件嗎?當(dāng)然是可以的。

使用原生事件

在React中我們也可以使用原生事件,那么如何進行綁定呢,因為React提供了ComponentDidMount這樣的API讓我們可以調(diào)用,那么要使用原生事件我們就可以在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。一定要手動的記住移除,不然可能會出現(xiàn)內(nèi)存泄漏問題。如果我們使用React合成事件,這些事React已經(jīng)幫你做好了。但是現(xiàn)實的情況下我們有一些場景是不得不用到原生的事件的那么該怎么做呢?

我們來看下邊的一個例子。例如我們要實現(xiàn)這樣的一個功能,在頁面上有個button,當(dāng)點擊它會出現(xiàn)一個圖片。當(dāng)點擊頁面的其他部分的時候,這個圖片會自動的消失,那么這樣的需求我們就不得不使用原生的事件了。話不多說我們來看代碼實現(xiàn)。

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'}} >
            ![](http://upload-images.jianshu.io/upload_images/65230-86cf2d60ac48f213.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
          </div>
      </div>
    )
  }
}
ReactDOM.render(<App />, document.getElementById('root'));

Open In CodePen

上邊一個例子中,我們實現(xiàn)了組件APP,他里邊有一個button,它上邊有一個handleClick的事件處理器,當(dāng)觸發(fā)時會把app的state里show制成true,這樣圖片就顯示了出來。同時在body上使用了原生事件,當(dāng)發(fā)生點擊事件的時候,就會被收起,這樣就簡單實現(xiàn)了需求的功能,那是看似這樣好像就沒有問題的,但是這其中有個bug,到底是什么問題呢,我們下篇文章繼續(xù)??纯丛录秃铣墒录煊玫哪切┦?。

參考文獻:
深入react技術(shù)棧

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,732評論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,214評論 3 426
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,781評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,588評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,315評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,699評論 1 327
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,698評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,882評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,441評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,189評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,388評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,933評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,613評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,023評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,310評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,112評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,334評論 2 377

推薦閱讀更多精彩內(nèi)容

  • 版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。 PS:轉(zhuǎn)載請注明出處作者:TigerChain地址:http...
    TigerChain閱讀 8,401評論 1 9
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,702評論 25 708
  • 原教程內(nèi)容詳見精益 React 學(xué)習(xí)指南,這只是我在學(xué)習(xí)過程中的一些閱讀筆記,個人覺得該教程講解深入淺出,比目前大...
    leonaxiong閱讀 2,851評論 1 18
  • 1 React合成事件特點 React自己實現(xiàn)了一套高效的事件注冊,存儲,分發(fā)和重用邏輯,在DOM事件體系基礎(chǔ)上做...
    Dabao123閱讀 1,791評論 1 1
  • 《蛙》講述了中國近六十年的農(nóng)村生育史,距離80,90年代的人都是遙遠的。 “計劃生育”成為整個故事的大背景,在那個...
    馬以黑閱讀 212評論 1 2