React事件優雅繫結

Ansen江發表於2019-01-11

2018-01-11 19:00 更新(目前最優解)

收到 同學的提醒,與其讓ESLint報錯,不如在呼叫時候做一些修改,上程式碼,就是在呼叫事件的時候,重新用箭頭函式再包裹一層,拍腦袋錶示為啥自己沒想到。


render(){
  return(
        <button 
          // 修改的部分在這裡,我知道這麼寫註釋是不對的,別學我
	  onClick={()=>{this.handleSubmit(params)}}
	>
	  提交
	</button>
  )
}
handleSubmit = () =>{
    // do something
}
複製程式碼

這樣真的是,在呼叫函式的時候使用箭頭函式並傳遞一個引數進去,這樣達成了期望的效果,又避免了ESLint的報錯,簡直6666…


下面的內容只是一些其他方法,隨意看看就好…

常規情況下使用React在節點上繫結事件是這樣

	render(){
        return(
        	<button onClick={this.handleClick.bind(this,params)}>Submit</button>
        )
	}
	handleClick(params){
		// do something
	}
複製程式碼

但是這種情況下每次資料發生變化的時候,都要重新呼叫render函式,事件也要重新繫結this指向,會比較耗費效能,於是出現了下面這種方式


在建構函式內部宣告事件方法
	constructor(props){
		super(props);
        // 在建構函式內部宣告事件方法
		this.handleClick = this.handleClick.bind(this)
	}
	render(){
        return(
        	<button onClick={this.handleClick}>Submit</button>
        )
	}
	handleClick(params){
		// do something
	}
複製程式碼

這種方法使得在方法在元件呼叫的時候就在constructer被宣告,當資料進行重新渲染時,事件不會在重新繫結this指向,但是這個操作有兩個弊端:

  1. 程式碼量增加,需要在constructer宣告;
  2. 在需要傳遞引數的時候還是需要重新bind(this,params);

ES6出現之後,我們可以通過箭頭函式=>來簡化this的指向問題:
	render(){
        return(
        	<button onClick={this.handleClick}>Submit</button>
        )
	}
	handleClick = () => {
		// do something
	}
複製程式碼

但是這個方式也只是解決了減少程式碼量的問題,在需要傳參的地方還是需要使用.bind(this,params)的方式,這就十分尷尬了。


使用ES6+Function.prototype的方法(不推薦,下面還提供了一個方法)

這個時候,我們會想何不為ES6重寫個bind。箭頭函式只寫一次,bind不用傳this,沒錯!我們就是這麼想的!

// 我們在Function的prototype上新建一個fBind方法,並寫在入口檔案中
Function.prototype.fBind = function(...args){
	var Fn = this;
	return function(e){
		Fn(...args,e);
	}
}
複製程式碼

然後,我們在元件中寫事件和傳參就可以變得無比清爽了...

	render(){
        return(
        	<button onClick={this.handleWithParams.fBind(params)}>有引數Submit</button>
        	<button onClick={this.handleWithoutParams}>無Submit</button>
        )
	}
    // 帶引數事件
	handleWithParams = (params) => {
		console.log(params);
		// do something
	}
    // 不帶引數事件
    handleWithoutParams = () =>{
        // do something
    }
複製程式碼

在不需要傳參的地方還是,唯一的缺陷是Eslint會報錯,提示不可以在Functionprototype上自定義方法,這個看你了…???

吐槽:掘金的markdown真難用,自己電腦上展示得好好的,貼過來就亂七八糟的……

相關文章