React 函數講解

學習目標

  • 純函數
  • React函數三種寫法
  • React事件處理

純函數

  • 首先得是一個函數。

  • 當給定相同的輸入(函數的參數)的時候,總是有相同的輸出(返回值)。

  • 沒有副作用。

  • 不依賴於函數外部狀態。

當一個函數滿足以上條件時,該函數可以稱爲是純函數。

// 非純函數let payload = 0;
function addOne(number) {
    ++payload;
    return number + payload;
}
addOne(1); // 2
addOne(1); // 3
addOne(1); // 4

// 純函數
function addOne(number) {
    return number + 1;
}
addOne(1); // 2
addOne(1); // 2
addOne(1); // 2

上面兩個栗子中,第一個就是典型的非純函數,當第一次執行 addOne(1) 其返回的值是 2 沒有錯,但是再次執行相同函數的時候,其返回的值不再是 2 了,而是變成了 3 ,對比上面列出的滿足純函數的條件,就會發現:

  • addOne() 給定相同的輸入的時候沒有返回相同的輸出;

  • addOne() 會產生副作用(會改變外部狀態 payload);

  • addOne() 依賴的外部狀態 payload 。

而第二個栗子就是一個純函數,它既不依賴外部狀態也不會產生副作用,且當給定相同輸入的時候,總是返回相同的輸出(執行任意多次 addOne(1) 總是返回 2 )。

React 官方定義

A JavaScript library for building user interfaces.
專注於構建 View 層的一個庫
 
UI 只是把數據通過映射關係變成另一種形式的數據。給定相同的輸入(數據)必然會有相同的輸出(UI),即一個簡單的純函數。 ---( Sebastian Markbåge [React 的核心開發者之一])
 
 
數據:父組件通過props傳遞給子組件,渲染相同的UI界面。
view: 包含數據的渲染結果。

實例一 非純函數

import React, { Children } from 'react';
import ReactDOM from 'react-dom';
class ShowTime extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      time: new Date().toLocaleTimeString()
    }
  }
  render () {
    return (
      <div>
        <h1>現在時間是:{this.state.time}</h1>
      </div>
    )
  }
}
ReactDOM.render(
  <ShowTime />, // 渲染父元素
  document.querySelector('#root') //尋找文件對象
)

從運行結果可知:該組件依賴於函數Date()。相同輸入,對應的輸出是不一樣的(時間不一樣)。
所以組件不是一個「純函數」。實際開發中組件之間還存在數據交互,因此非純函數也是常見的。
 

React函數三種寫法

  • 寫法一:通過bind實現函數內部this指向該實例,bind的第一個參數是context,即this。
import React, { Children } from 'react';
import ReactDOM from 'react-dom';
import { render } from '@testing-library/react';
class Test extends React.Component {
    constructor(props) {
        super(props);
        this.setName = this.setName.bind(this);
    }
}
/**
* @param name
*/
setName(name) {
  ...
};
render() {
    return (
        <div>
            <button onClick={this.setName}>點擊獲取姓名</button>
        </div>
    )
}
onClick={this.setName},函數類似是一個參數傳遞。重點是事件bind。
 
  • 寫法二:箭頭式函數(聲明時採用箭頭函數的形式)
import React, { Children } from 'react';
import ReactDOM from 'react-dom';
import { render } from '@testing-library/react';
class Test extends React.Component {
    constructor(props) {
        super(props);
        ...
    }
}
/**
* @param name
*/
setName = (name) => {
  ...
};
render() {
    return (
        <div>
            <button onClick={this.setName}>點擊獲取姓名</button>
        </div>
    )
}

構造器中無需綁定事件。箭頭會從自己的作用域鏈上層繼承this,這個this就會指向這個類的實例。

  • 寫法三:箭頭式函數(調用時採用箭頭函數傳參)
import React, { Children } from 'react';
import ReactDOM from 'react-dom';
import { render } from '@testing-library/react';
class Test extends React.Component {
    constructor(props) {
        super(props);
        ...
    }
}
/**
* @param name
*/
setName(name) {
  ...
};
render() {
    return (
        <div>
            <button onClick={(name) => this.setName(name)}>點擊獲取姓名</button>
        </div>
    )
}

類似於寫法二,在調用處使用箭頭函數。

React 事件處理

React中的事件處理一般與函數相結合。
 
HTML 通常寫法是:
<button οnclick="activateLasers()">
  激活按鈕
</button>

React 中寫法爲:

<button onClick={activateLasers}>
  激活按鈕
</button>

React 寫法特點

  • React 事件綁定屬性的命名採用駝峯式寫法,而不是小寫。
  • 如果採用 JSX 的語法你需要傳入一個函數作爲事件處理函數,而不是一個字符串(DOM 元素的寫法)
向事件處理程序傳參
 

刪除id對應的那一行。

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
 
上述兩種方式是等價的。參數 e 作爲 React 事件對象將會被作爲第二個參數進行傳遞。通過箭頭函數的方式,事件對象必須顯式的進行傳遞,但是通過 bind 的方式,事件對象以及更多的參數將會被隱式的進行傳遞。
 

參考鏈接:

https://segmentfault.com/a/1190000017750929 [React 中的函數式思想]

 
https://www.runoob.com/react/react-event-handle.html [React 事件處理]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章