解釋React爲什麼onClick函數綁定都用箭頭函數()=>{}

前言,起因在於今日同事問起,發現不能很好的解釋這個問題,所以自己下來重新屢了一下思路,記錄一下。

一、什麼是箭頭函數,以及爲什麼React裏要用箭頭函數

1. 下面這兩個函數相同。只是react組件化,不支持在組建內部寫function,所以現在用箭頭函數代替js裏的寫法

// 傳參寫法
// 原生js寫法
function test(params) {
    
    console.log('this = ',this)
}

<div onClick={test(123)}></div>

//等價於下面react寫法


test2 = param => () => {
    console.log('param = ',param)
}

<div onClick={this.test2(123)}></div>

//不傳參寫法
function test(){}   <=>   test = () => {}

2. 你肯定會繼續問,那如果只是替換原來的function寫法, 直接在react裏寫

<div onClick={test(123)}></div>

爲什麼要變成 this.test(123) 呢? 

這是因爲 在使用ES6 classes或者純函數時,React不會自動綁定this到當前組件上,需要手動實現this的綁定。

如果在React裏繼續 test(123),此時test的對象指向的是window,而不是改組建內部,所以會是undefined,這個時候,編譯器檢測到你onClick 綁定了一個 undefined, 所以會報錯

以上,按照我的思路,首先,你要了解箭頭函數其實是等價替換原有js的函數寫法,其次,比原有寫法多寫this是因爲react不會自動綁定this到當前組建。

二、你還有疑惑嗎

如果我們一開始不知道箭頭函數等價替換了function函數,我們就很容易在React裏把函數寫成下面這個樣子

test(param){
    console.log(param);
}

<div onClick={this.test(123)}></div>

期望的效果是,點擊一次這個div,就打印一次傳入的參數123,但是,你發現,只在頁面開始渲染的時候打印了函數,而點擊的時候沒有反應。 這是爲什麼呢?

一開始會打印,是因爲頁面在渲染的時候,把this.test()當成一個函數預執行,所以一開始打印123,而這個函數返回的是undefined。所以你點擊的時候,不會有輸出。此時你的 onClick = undefined;

那如果我是變態一點,給這個函數加返回值

test(param){
    console.log(param);
    return param
}

<div onClick={this.test(123)}></div>

會發生什麼呢? 答案是:會報錯。因爲這個時候 onClick = 123; 不是一個函數,所以報錯。

三、ES6爲什麼要引入箭頭函數呢?

   這裏直接用一下廖雪峯老師的例子。

接上,如果沒有箭頭函數,我們需要用hack的寫法去解決this作用域的問題。

var obj = {
    birth: 1990,
    getAge: function () {
        let that = this;
        var b = this.birth; // 1990
        var fn = function () {
            return new Date().getFullYear() - that.birth; // 此時that指向當前作用域
        };
        return fn();
    }
};

obj.getAge() // 輸出 29  上面輸出25是因爲廖老師寫這篇文章的時候是15年,現在19年啦

四、React裏爲什麼要bind一下呢?

理由同上面 (一.2) 裏提過的,react不會自動綁定函數。比如你可能會這樣寫

test(){
    console.log('123');
}

<div onClick={this.test}></div>

你發現每次點擊,確實會打印123,但是你並沒有按照箭頭函數的形式寫,你可能會覺得,這樣也能用,但是,如果你試着打印一下。


constructor(props) {
  super(props);
  this.state = {
    visible: true,
  }
}
test(){
   console.log(this.state.visible);
}

你會發現打印的是undefined。這就是因爲不用箭頭函數,組件裏的函數不會自動綁定this,這個時候,你需要在constructor裏綁定this。

constructor(props) {
  super(props);
  this.state = {
    visible: true,
  }
  this.test = this.test.bind(this);
}
test(){
   console.log(this.state.visible);
}

這樣每次點擊,就可以打印出來visible的值了。但這種寫法有一種缺陷,就是不能傳參(可能是我目前沒了解到這種寫法傳參的方法)

補一個關於函數和方法的定義

  函數(function): 函數是帶有名稱(named)和參數的JavaScript代碼段,可以一次定義多次調用。

  方法(method): 當將函數和對象合寫在一起時,函數就變成了 "方法"(method)// 當函數賦值給對象的屬性,我們稱爲"方法"

  也就是函數和方法本質上是一樣的,只不過方法是函數的特例,是將函數賦值給了對象。

 

完結。關於箭頭函數和React裏的使用的原因,以上就是我自己的看法,如果哪裏說的不對,請大家指出來,共同進步。最近無時無刻不在感覺自己知識的不牢固。還是要踏實學習,勤思考纔行..

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章