在 React 底層,主要對合成事件做了兩件事:事件委派和自動綁定。
1. 事件委派
在使用 React 事件前,一定要熟悉它的事件代理機制。它並不會把事件處理函數直接綁定到 真實的節點上,而是把所有事件綁定到結構的最外層,使用一個統一的事件監聽器,這個事件監 聽器上維持了一個映射來保存所有組件內部的事件監聽和處理函數。當組件掛載或卸載時,只是 在這個統一的事件監聽器上插入或刪除一些對象;當事件發生時,首先被這個統一的事件監聽器 處理,然后在映射里找到真正的事件處理函數並調用。這樣做簡化了事件處理和回收機制,效率 也有很大提升。 

2. 自動綁定
在 React 組件中,每個方法的上下文都會指向該組件的實例,即自動綁定 this 為當前組件。 而且 React 還會對這種引用進行緩存,以達到 CPU 和內存的最優化。在使用 ES6 classes 或者純 函數時,這種自動綁定就不復存在了,我們需要手動實現 this 的綁定。
現在我們來看幾種綁定的方法:
- bind 方法。這個方法可以幫助我們綁定事件處理器內的 this ,並可以向事件處理器中傳 5 遞參數,比如:
import React, { Component } from 'react'; class App extends Component { handleClick(e, arg) { console.log(e, arg); } render() { // 通過bind方法實現,可以傳遞參數 return <button onClick={this.handleClick.bind(this, 'test')}>Test</button>; } }
如果方法只綁定,不傳參,那 stage 0 草案中提供了一個便捷的方案1——雙冒號語法,其作 用與 this.handleClick.bind(this) 一致,並且 Babel 已經實現了該提案。比如:
import React, { Component } from 'react’; class App extends Component { handleClick(e) { console.log(e); } render() { return <button onClick={::this.handleClick}>Test</button>; } }
- 構造器內聲明。在組件的構造器內完成了 this 的綁定,這種綁定方式的好處在於僅需要 進行一次綁定,而不需要每次調用事件監聽器時去執行綁定操作:
import React, { Component } from 'react'; class App extends Component { constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); } handleClick(e) { console.log(e); } render() { return <button onClick={this.handleClick}>Test</button>; } }
- 箭頭函數。箭頭函數不僅是函數的“語法糖”,它還自動綁定了定義此函數作用域的 this, 因此我們不需要再對它使用 bind 方法。比如,以下方式就能運行:
import React, { Component } from 'react'; class App extends Component { const handleClick = (e) => { console.log(e); }; render() { return <button onClick={this.handleClick}>Test</button>; } } 或 import React, { Component } from 'react'; class App extends Component { handleClick(e) { console.log(e); } render() { return <button onClick={() => this.handleClick()}>Test</button> }}
使用上述幾種方式,都能夠實現在類定義的組件中綁定 this 上下文的效果。
(原文出自《深入react技術棧》)
(原文出自《深入react技術棧》)