React組件方法的兩種定義方式

在React組件中,一般可經過兩種方式來定義組件的方法:普通函數、箭頭函數;做爲方法存在,那麼二者到底有什麼區別呢?javascript

方法掛載點

es6,有一部分是對過去版本的js進行包裝。在使用es6語法的React組件中,要剖析普通函數和箭頭函數定義方法有什麼區別,可經過babel轉換,轉換成咱們熟悉的js語法,看看兩者的原本面目。java

舉個例子:git

class Hello {

        greet(){ },

        say = () => { },
    }
複製代碼

babel轉換後,突出重點,大體以下:es6

function Hello(){
    this.say = () => { }
}
function.prototype.greet = function() { }
複製代碼

經過轉義後的代碼,可看到區別:github

  • 普通函數被定義爲類的原型方法bash

    經過function建立的原型方法。babel

  • 箭頭函數被定義爲類的實例方法函數

    經過箭頭方法建立的實例方法。性能

原型方法和實例方法?

  • 屬性查找 在查找實例的屬性和方法時,首先會在實例的屬性、方法中查找,當沒有找到時,在循着實例的原型鏈進行查找,直到查找到對應的屬性和和方法,或者最後什麼都查不到。這就和性能相關了,查找屬性、方法的時間有過不一樣。
  • 調用 實例方法只能經過實例調用,而原型方法還能經過函數調用,好比:A.prototype.click()。

this指向

在es6以前的js語法中,this的指向是一個比較多場景的問題在Js中,在此忽略。咱們今天只講在React組件中這兩種方法的this指向。從上面得出,兩個方法的在類中的的掛載點是不一樣的,然而,這並非致使他們做爲方法,表現差別有所不一樣的緣由,更多的是他們的的建立方式致使this有所區別。ui

箭頭函數定義的方法

箭頭函數定義方法時,this指向的是函數定義時的做用域。看例子:

function A(){
    this.num = 2;
    this.handleClick = () => { console.log(this.num) };
}

const B = new A();

// 第一種狀況
B.handleClick(); //2
// 第二種狀況
const fn = b.handleClick;
fn(); // 2
複製代碼

普通函數定義的方法

而普通函數的this,倒是根據調用它時的對象有所關係。

function A(){
   this.num = 2
   this.handleClick = function(){console.log(this.num) }
}

const B = new A();

//如下都爲嚴格模式下

B.handleHover(); // 2

const fn = B.handleHover;

fn(); // 報錯,由於在嚴格模式下this爲undefined
複製代碼

不管是原型方法或者是實例方法,致使在調用時,this不一樣,緣由在於他們的建立方式,當使用箭頭函數建立,那麼this將指向函數定義時的做用域;而當使用普通的function建立時,this的指向和函數的調用環境有關,(關於普通函數this的指向有所不瞭解,可經過《你不知道的javascript》熟悉)

因此,不管如何,箭頭函數的this都不會發生改變,this指向的是組件;而普通函數的this隨着調用場景的變化有所變化。

方法使用

若是咱們在須要將組件的一個方法綁定給一個子元素,爲了保證函數中的this指向的是這個React組件(當函數須要藉助組件的一些狀態和屬性時)。

class Hello extends React.PureComponent {
    greet() {console.log(this)}
    say = () => { console.log(this)}
    
    render() {
        return (
            <div>
                // 普通函數
                <div onClIck={this.greet.bind(this)}>普通函數</div>
                <div onClick={(e) => this.greet(e)}></div>

                // 箭頭函數
                <div onClick={this.say}></div>
            </div>
        )
    }
}

複製代碼

普通函數的傳遞方法視覺上就以爲有點繁瑣,除此以外,更重要的是性能方面。

React的生命週期中,shouldUpdateComponent,當shouldUpdateComponent返回false時,組件將不會從新render,子組件也可避免從新render。在 React 15.3.0 ,Reac可經過React.Purecomponent定義組件,當shouldUpdateComponent進行shallow compare時,避免一些沒必要要的render。而經過普通函數定義的方法,經過bind綁定後,每次父組件發生render時,方法就得從新bind(this),對於子組件而言,它的props、state發生了改變,則必須發生從新渲染。

若是咱們定義的方法不用綁定給子元素,而是被組件本身內部的函數調用,箭頭函數和普通函數均可以用來定義方法。

class DownloadGameBtn extends React.PureComponent {
    constructor(props) {
        super(props);
        this.initInfo();
        this.initSize();
    }
    initInfo() {
       console.log(this); // 指向DownloadGameBtn組件 
    }
    initSize = () => {
        console.log(this) // 指向DownloadGameBtn組件
    }
}
複製代碼

參考

ES6 Class Methods 定義方式的差別

函數做爲React組件的方法時, 箭頭函數和普通函數的區別是什麼?

最後

在工做中遇到的問題,經過各類資料查找,進行總結和概括,感謝各位前輩的分享。這是第一次在一個公共社區發表本身的總結文章,寫的有點蠢蠢的,但願這些能夠幫到和我同樣遇到相似困惑的朋友。而後,你們輕點噴。

相關文章
相關標籤/搜索