在提及react的函數綁定以前,咱們有必要了解下bind函數的做用是什麼,函數的執行的上下文以及其默認的this是指向的哪裏?有點抽象?那麼你能夠去看下下面的兩個方法的執行會有什麼區別吧。javascript
let customer={
name:'Robin',
getName:function(){
console.log(this.name);
}
}
customer.getName();//Robin
let getName = customer.getName;
getName();// CodePen
let getNameWithCustomer = customer.getName.bind(customer);
getNameWithCustomer();// Robin
複製代碼
若是你猜不出結果,能夠看下個人codePen連接:連接,這是爲何呢?這是由於上下文不一樣,也就是this不一樣,當你經過賦值拿到方法,方法執行時會先去查看其上下文的this是什麼,而不是直接使用其來源於哪一個對象的。那麼若是咱們想使用對象裏的屬性,可使用bind方法綁定一個指定的對象。因而咱們又獲得了咱們指望的name:robin值。html
從上面的結果中,咱們獲得瞭如下的幾個認知:前端
1 函數調用時,只取決於其實際執行環境,與來源無關
2 若是咱們但願函數執行或者函數拷貝時,不丟失參數,或者避免參數錯誤,咱們應該將參數傳入,而不要過分依賴當前this的上下文。
3 若是咱們只是一個工具函數,那麼你可能沒有特別的場景必定要綁定什麼,好比你定義一個add方法計算兩個參數的和,那麼你不須要綁定其餘的對象或者上下文。
4 若是咱們但願函數執行時,在某個環境或者類內綁定指定的上下文,那麼你須要顯性的綁定this纔可使用這個對象裏的屬性以及屬性方法。
5 若是咱們喜歡函數執行時,但願能夠根據需求綁定任意的對象,也建議函數定義時,考慮好這一點,並綁定時綁定其對應的對象,這時候極可能你綁定的不是"this"。
6 bind方法只是改變上下文,並不會致使函數的執行。java
備註:更多關於this的文章,詳解請看我另外兩篇文章,有很是詳盡的說明:神奇的this:連接, js中的做用域:連接react
react中的事件綁定,咱們按照無參和有參兩種。無參很是簡單,直接綁定函數便可。當咱們須要傳遞參數時,剛入門前端的人可能會直接綁定參數。這樣會致使兩個錯誤,1 丟失了事件參數 2 致使了函數的直接執行,而不是點擊後執行。(做爲常識,咱們還要知道,默認的點擊事件等事件是會返回event對象的哦)。git
備註:若是你不清楚前端的事件流機制,能夠查看個人js中事件流機制:連接github
handleClick(e){
const {type} = e;// click
}
render(){
const text = 'button text';
return (
<button onClick={this.handleClick}></button>
)
}
// 直接傳參會致使錯誤
render(){
const text = 'button text';
return (
<button onClick={this.handleClick(text)}></button>
)
}
// 經過箭頭函數 避免這種問題
render(){
const text = 'button text';
return (
<button onClick={(e,text) => this.handleClick(e,text)}></button>
)
}
複製代碼
因此你經過箭頭函數避免了上面的錯誤,但這種使用與咱們的常規使用是不一樣的。爲何呢?由於咱們通常在react組件中須要常用當前組件的上下文,包括當前組件的state、方法以及傳入的屬性等。這時候,咱們想起了前言中的bind語法,其能夠改變上下文的this,支持事件獲知的同時,綁定當前對象。並且咱們經過bind的語法清楚,其不但能夠綁定上下文,還能夠支持靈活的傳參,若是你不清楚其基本語法,能夠查看js- MDN的介紹:連接.框架
下面的內容借鑑於react中文官網的教程--傳遞函數給組件,作了簡單的整理:原文連接:連接,有如下的幾種方式。函數
// 第一種 :render 中bind綁定
render(){
const text = 'button text';
return (
<button onClick={ this.handleClick.bind(this,text)}></button>
)
}
// 第二種 :constructor bind綁定
constructor(props){
this.handleClick = this.handleClick.bind(this);
}
render(){
const text = 'button text';
return (
<button onClick={ (e,text)=> this.handleClick(e,text)}></button>
)
}
// 第三種 :class func 箭頭函數 <=> 上面的調用方法均是常規方法寫法
handleClick=()=>{
}
render(){
const text = 'button text';
return (
<button onClick={(e,text)=> this.handleClick(e,text)}></button>
)
}
複製代碼
須要注意的是,在官網文檔中,咱們看到在rende函數中使用箭頭函數以及使用bind綁定都會影響性能,而在constructor中將全部函數綁定一遍又過於繁瑣,咱們通常的框架中習慣於使用class 屬性函數,--箭頭函數的方式實現,也就是上面代碼中的第三種,一樣,咱們在react ant的ui框架的input組件中找到了icon的元素事件傳遞的方式也是第三種,查看連接。參考下面的原代碼:工具
handleReset = (e: React.MouseEvent<HTMLElement, MouseEvent>) => {
this.setValue('', e, () => {
this.focus();
});
};
renderClearIcon(prefixCls: string) {
const { allowClear } = this.props;
const { value } = this.state;
if (!allowClear || value === undefined || value === null || value === '') {
return null;
}
return (
<Icon type="close-circle" theme="filled" onClick={this.handleReset} className={`${prefixCls}-clear-icon`} role="button" /> ); } 複製代碼
經過本文但願你能清楚咱們爲何要bind this,以及如何正確綁定的一些可行方式,和每種方式的優缺點,還有一些如何避免低級錯誤,致使函數直接執行的緣由。一樣,咱們也知道了通常的ui框架中採用的是哪一種方式--類屬性的方式。
更多精彩內容跳轉:原文語雀鏈接
咱們一塊兒從從小白到大師。 --- Robin