摘要:處理事件響應是應用中非常重要的一部分。中,處理事件響應的方式有多種。關于事件響應的回調函數,還有一個地方需要注意。不管你在回調函數中有沒有顯式的聲明事件參數,都會把事件作為參數傳遞給回調函數,且參數的位置總是在其他自定義參數的后面。
React中定義一個組件,可以通過React.createClass或者ES6的class。本文討論的React組件是基于class定義的組件。采用class的方式,代碼結構更加清晰,可讀性強,而且React官方也推薦使用這種方式定義組件。
處理事件響應是Web應用中非常重要的一部分。React中,處理事件響應的方式有多種。
1.使用箭頭函數先上代碼:
//代碼1 class MyComponent extends React.Component { render() { return ( ); } }
當事件響應邏輯比較復雜時,再把所有的邏輯直接寫在onClick的大括號內,就會導致render函數變得臃腫,不容易直觀地看出組件render出的元素結構。這時,可以把邏輯封裝成組件的一個方法,然后在箭頭函數中調用這個方法。如下所示:
//代碼2 class MyComponent extends React.Component { constructor(props) { super(props); this.state = {number: 0}; } handleClick() { this.setState({ number: ++this.state.number }); } render() { return (); } }{this.state.number}
這種方式最大的問題是,每次render調用時,都會重新創建一個事件的回調函數,帶來額外的性能開銷,當組件的層級越低時,這種開銷就越大,因為任何一個上層組件的變化都可能會觸發這個組件的render方法。當然,在大多數情況下,這點性能損失是可以不必在意的。這種方式也有一個好處,就是不需要考慮this的指向問題,因為這種寫法保證箭頭函數中的this指向的總是當前組件。
2.使用組件方法代碼先:
//代碼3 class MyComponent extends React.Component { constructor(props) { super(props); this.state = {number: 0}; this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState({ number: ++this.state.number }); } render() { return (); } }{this.state.number}
這種方式的好處是每次render,不會重新創建一個回調函數,沒有額外的性能損失。需要注意的是,使用這種方式要在構造函數中為事件回調函數綁定this: this.handleClick = this.handleClick.bind(this),否則handleClick中的this是undefined。這是因為ES6 語法的緣故,ES6 的 Class 構造出來的對象上的方法默認不綁定到 this 上,需要我們手動綁定。每次都手動綁定this是不是有點蛋疼?好吧,讓我們來看下一種方式。
3.屬性初始化語法(property initializer syntax)使用ES7的 property initializers,代碼可以這樣寫:
//代碼4 class MyComponent extends React.Component { constructor(props) { super(props); this.state = {number: 0}; } handleClick = () => { this.setState({ number: ++this.state.number }); } render() { return (); } }{this.state.number}
哈哈,再也不用手動綁定this了。但是你需要知道,這個特性還處于試驗階段,默認是不支持的。如果你是使用官方腳手架Create React App 創建的應用,那么這個特性是默認支持的。你也可以自行在項目中引入babel的transform-class-properties插件獲取這個特性支持。
4.回調函數傳參問題事件的回調函數默認是會被傳入一個事件對象Event作為參數的。如果我想傳入其他參數給回調函數應該怎么辦呢?
使用第一種方式的話很簡單,直接傳就可以了:
//代碼5 class MyComponent extends React.Component { constructor(props) { super(props); this.state = { list: [1,2,3,4], current: 1 }; } handleClick(item,event) { this.setState({ current: item }); } render() { return (
使用第二種方式的話,可以把綁定this的操作延遲到render中,在綁定this的同時,綁定額外的參數:
//代碼6 class MyComponent extends React.Component { constructor(props) { super(props); this.state = { list: [1,2,3,4], current: 1 }; } handleClick(item) { this.setState({ current: item }); } render() { return (
使用第三種方式,解決方案和第二種基本一致:
//代碼7 class MyComponent extends React.Component { constructor(props) { super(props); this.state = { list: [1,2,3,4], current: 1 }; } handleClick = (item) => { this.setState({ current: item }); } render() { return (
不過這種方式就有點雞肋了,因為雖然你不需要通過bind函數綁定this,但仍然要使用bind函數來綁定其他參數。
關于事件響應的回調函數,還有一個地方需要注意。不管你在回調函數中有沒有顯式的聲明事件參數Event,React都會把事件Event作為參數傳遞給回調函數,且參數Event的位置總是在其他自定義參數的后面。例如,在代碼6和代碼7中,handleClick的參數中雖然沒有聲明Event參數,但你依然可以通過arguments[1]獲取到事件Event對象。
總結一下,三種綁定事件回調的方式,第一種有額外的性能損失;第二種需要手動綁定this,代碼量增多;第三種用到了ES7的特性,目前并非默認支持,需要Babel插件的支持,但是寫法最為簡潔,也不需要手動綁定this。推薦使用第二種和第三種方式。
歡迎關注我的公眾號:老干部的大前端,領取21本大前端精選書籍!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/84239.html
摘要:如果這個結構非常復雜,那么想要安全優雅地取出一個值,也并非簡單。這是為了在對象中相關取值的過程,需要驗證每一個和的存在性。并且這個數據結構必然是動態生成的,存在有時有時的情況。在測試過程中,很難復現。 古有趙子龍面對沖鋒之勢,有進無退,陷陣之志,有死無生的局面,能萬軍叢中取敵將首級。在我們的Javascript中,往往用對象(Object)來存儲一個數據結構。如果這個結構非常復雜,那么...
摘要:如果這個結構非常復雜,那么想要安全優雅地取出一個值,也并非簡單。這是為了在對象中相關取值的過程,需要驗證每一個和的存在性。并且這個數據結構必然是動態生成的,存在有時有時的情況。在測試過程中,很難復現。 古有趙子龍面對沖鋒之勢,有進無退,陷陣之志,有死無生的局面,能萬軍叢中取敵將首級。在我們的Javascript中,往往用對象(Object)來存儲一個數據結構。如果這個結構非常復雜,那么...
摘要:二需要處理哪些異常對于前端來說,我們可做的異常捕獲還真不少。總結一下,大概如下語法錯誤代碼異常請求異常靜態資源加載異常異常異常跨域崩潰和卡頓下面我會針對每種具體情況來說明如何處理這些異常。 前端一直是距離用戶最近的一層,隨著產品的日益完善,我們會更加注重用戶體驗,而前端異常卻如鯁在喉,甚是煩人。一、為什么要處理異常?異常是不可控的,會影響最終的呈現結果,但是我們有充分的理由去做這樣的事...
閱讀 1310·2021-11-15 11:37
閱讀 3501·2021-11-11 16:55
閱讀 1750·2021-08-25 09:39
閱讀 3216·2019-08-30 15:44
閱讀 1734·2019-08-29 12:52
閱讀 1405·2019-08-29 11:10
閱讀 3241·2019-08-26 11:32
閱讀 3223·2019-08-26 10:16