每日質量NPM包事件綁定_bindme(詳解React的this)

1、bindme

官方定義: is a helper to bind a list of methods to an object referencecss

理解: 由於不推薦在render()裏構建函數,做者就用了6行代碼封裝了函數綁定事件的代碼.
bindme的npm包實際上由6行ES5代碼組成,可是確實方便了不少.這個包值得一用react

2、用法

代替箭頭函數和多層bind

有時候咱們並不會直接在建立事件的時候bind,而是統一在constructor上綁定事件,若是一個模塊大起來,就會出現好幾十行綁定事件的代碼,用bindme能夠很好解決.例如面試

//原寫法
this.clickEvent1 = this.clickEvent1.bind(this)
this.clickEvent2 = this.clickEvent2.bind(this)
this.clickEvent3 = this.clickEvent3.bind(this)
this.clickEvent4 = this.clickEvent4.bind(this)
this.clickEvent5 = this.clickEvent5.bind(this)

//bindme寫法
bindme(this, 'clickEvent1', 'clickEvent2', 'clickEvent3', 'clickEvent4', 'clickEvent5')

又好看又方便npm

也能夠在super構建實例的時候綁定函數

bindme(super(props),
    'clickEvent1',
    'clickEvent2',
    'clickEvent3',
    'clickEvent4',
    'clickEvent5',
)

就是這麼簡單的用法, 咱們能夠看看它的源碼轉換成ES6是怎麼樣的性能

const bindme = (self, ...funcs) => {
  funcs.forEach(func => {
    if (self[func]) {
      self[func] = self[func].bind(self)
    } else {
      console.error(`Method ${func} is not defined`)
    }
  })
}

其實也就是收集全部的事件,再統一bind,若是不存在的拋出異常.咱們在平時也會常常封裝一些相似這些小的便捷操做this

結合React

import React,{ PureComponent } from 'react'

import bindme from 'bindme'
import './style.css'
export default class BindmeComp extends PureComponent{
    constructor(props){
        bindme(super(props),
            'bindmeOnMouseOver'
        )

        this.initClickMode = this.initClickMode.bind(this)
        
        bindme(this, 'bindmeFirClickMode', 'bindmeSecClickMode')
    }

    noThisClickMode(){
        console.log('未綁定this事件 =========>', this)
    }

    initClickMode(){
        console.log('普通bind事件 ===========>', this)
    }

    arrowClickMode = () => {
        console.log('箭頭函數bind事件 ===========>', this)
    }

    bindmeFirClickMode(){
        console.log('bindme事件1 ===========>', this)
    }

    bindmeSecClickMode(){
        console.log('bindme事件2 ===========>', this)
    }

    bindmeOnMouseOver(){
        console.log('bindme事件3 ===========>', this)
    }

    render(){
        return(
            <div>
                <div className="list">
                    <span>未綁定this事件</span>
                    <button onClick={ this.noThisClickMode }>點擊</button>
                </div>
                <div className="list">
                    <span>普通bind事件</span>
                    <button onClick={ this.initClickMode }>點擊</button>
                </div>
                <div className="list">
                    <span>箭頭函數事件</span>
                    <button onClick={ this.arrowClickMode}>點擊</button>
                </div>
                <div className="list">
                    <span>bindme</span>
                    <button onClick={ this.bindmeFirClickMode }>點擊</button>
                </div>
                <div className="list">
                    <span>bindme2</span>
                    <button onClick={ this.bindmeSecClickMode } >點擊</button>
                </div>

                <div className="list">
                    <span>bindme3</span>
                    <button onMouseOver={ this.bindmeOnMouseOver } >滑過</button>
                </div>
            </div>
        )
    }
}

上面基本覆蓋了經常使用的事件綁定狀況.咱們看看都會輸出什麼?spa

能夠看到,除了第一個this爲undefined外,其餘都是正常綁定在了組件上code

擴展一下React的this

咱們先從咱們最熟悉js的this提及;對象

面試官常常會問,什麼是this?this指向什麼?
通常來講:
誰調用該function,該函數的this就指向這個調用方

有一個特殊的狀況,ES6的箭頭函數,也是面試官特別喜歡的一個東西(但它確實好用),因爲箭頭函數不存在this,因此它的this是由上一層繼承而來的.因此能夠得出結論箭頭函數的this始終指向構造時的對象,而不是使用時的對象

另外箭頭函數還有一些不一樣於普通函數的特性,好比: 不能夠看成構造函數使用,即不能夠new. 不可使用arguments屬性等等

總結一句話就是:
普通函數this是動態的,而箭頭函數的this是靜態的

咱們細說一下React的this.

由於React組件是經過class構造的,因此組件裏的全部屬性,全部方法均可以經過this來獲取,例如咱們常用的屬性state.就能夠經過this.state.xxx獲取

因此咱們只須要保證this永遠指向該構造對象(組件)便可,因此咱們通常不會經過function來建立函數(會使得this動態指向調用function的對象), 而且:

React組件類的方法沒有默認綁定this到組件實例,須要手動綁定。

因此就衍生出了綁定this的方法;經常使用的有四種,咱們通常會使用在constructor裏面bind

//優先級最高
constructor(props){
    super(props);
    
    this.handleEvent = this.handleEvent.bind(this)
}

這種和直接在構建事件中綁定很像對吧?

<input onChange={this.handleEvent.bind(this)} />

原理雖然是同樣的,可是性能卻差了一大截.爲何?

咱們知道只要state值改變了,就會致使render從新渲染,若是直接在建立事件綁定,那每一次渲染的時候都須要從新綁定一次,會大大下降性能.相反,只要在構造的時候綁定,不管渲染多少次,綁定都仍是一次

此外還有比較經常使用的箭頭函數綁定法和::綁定法
前面也介紹了箭頭函數this的知識,因此在React出現也是蠻高的

handleEvent = () => {
    ...
}

<input onChange={this.handleEvent} />

::雖然也能夠綁定this,可是由於不能傳參數,因此不常用

handleEvent = () => {
    ...
}

<input onChange={::this.handleEvent} />
相關文章
相關標籤/搜索