React組件中怎么使用bind-創(chuàng)新互聯(lián)

今天就跟大家聊聊有關(guān)React 組件中怎么使用bind,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

淮安網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)公司,淮安網(wǎng)站設(shè)計制作,有大型網(wǎng)站制作公司豐富經(jīng)驗。已為淮安千余家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)營銷網(wǎng)站建設(shè)要多少錢,請找那個售后服務(wù)好的淮安做網(wǎng)站的公司定做!

React 組件中處理 onClick 類似事件綁定的時候,是需要顯式給處理器綁定上下文(context)的,這一度使代碼變得冗余和難看。

class App extends Component {
 constructor() {
  super();
  this.state = {
   isChecked: false
  };
 }
 render() {
  return (


   <div className="App">
    <label >
     check me:
     <input
      type="checkbox"
      checked={this.state.isChecked}
      onChange={this.toggleCheck}
     />
    </label>
   </div>
  );
 }

 toggleCheck() {
  this.setState(currentState => {
   return {
    isChecked: !currentState.isChecked
   };
  });
 }
}

頁面上放了一個 checkbox 元素,點擊之后切換其選中狀態(tài)。這是很直觀的一段代碼,但并不會像你想的那樣正常工作。

React 組件中怎么使用bind

事件處理器上下文丟失的報錯

因為 checkbox 的 onChange 事件處理器中,找不到 React 組件的 setState 方法,這說明其執(zhí)行時的上下文不是該組件,而是別的什么東西,具體我們來調(diào)試下。

React 組件中怎么使用bind

調(diào)試查看丟失上下文后 this 的值

出乎意料,是 undefined,這個方法在一個完全野生的環(huán)境下執(zhí)行,沒有任何上下文。

WHY

當然這并不是 React 的鍋,這是 JavaScript 中 this 的工作原理。具體可參見 Chapter 2: this All Makes Sense Now! 來追溯其底層原因,簡單來講 this 的值取決于函數(shù)調(diào)用的方式。

默認的綁定

function display(){
 console.log(this)
}

display() // 嚴格模式下為全局 `window`,非嚴格模式下為 `undefined`

隱式綁定

通過對象來調(diào)用,該函數(shù)的上下文被隱式地指定為該對象。

var obj = {
 name: 'Nobody',
 display: function(){
  console.log(this.name);
  }
 };
 obj.display(); // Nobody. 里面取的是 obj 身上的 `name` 屬性

但,如果把該對象上的方法賦值給其他變量,或通過參數(shù)傳遞的形式,再執(zhí)行,那光景就又不一樣了。

var obj = {
 name: "Nobody",
 display: function() {
  console.log(this.name);
 }
};
var name = "global!";
var outerDisplay = obj.display;
outerDisplay(); // global! 這里取到的 `name` 是全局中的內(nèi)個

這里賦值給 outerDisplay 后再調(diào)用,等同于調(diào)用一個普通函數(shù),而不是對象中的那個,所以此時 this 為全局對象,剛好全局里面有定義一個 name 變量。同樣地,如果是嚴格模式下,因為此時 this 為 undefined,所以訪問不到所謂的 undefiend.name,于是會拋錯。

function invoker(fn) {
 fn();
}

setTimeout( obj.display, 1000 ); // global!
invoker(obj.display); // global!

這里 setTimeout 調(diào)用的時候,因為它的簽名實際上是 setTimeout(fn,delay),所以,可以理解為將 obj.display 賦值給了它的入?yún)?fn,實際上執(zhí)行的是 fn 而不再是對象上的方法了。對于 invoker 函數(shù)也是一樣的道理。

強制綁定

這個時候,bind 就成了那個拯救世界的英雄,任何時間我們都可以通過它來顯式地指定函數(shù)的執(zhí)行上下文。

var name = “global!”;
obj.display = obj.display.bind(obj); 
var outerDisplay = obj.display;
outerDisplay(); // Nobody

bind 將指定的上下文與函數(shù)綁定后返回一個新的函數(shù),這個新函數(shù)再拿去賦值或傳參什么的都不會對其上下文產(chǎn)生影響了,執(zhí)行時始終是我們指定的那個。

現(xiàn)場還原

有了上面的背景,就可以還原文章開頭的問題了,即事件處理器的上下文 丟失的問題。

JSX 中的 HTML 標簽本質(zhì)上對應(yīng) React 中創(chuàng)建該標簽的一個函數(shù)。比如你寫的 div 編譯會其實是 React.createElement(‘div')。所以當你書寫 <Input> 時其實是調(diào)用了 React.createElement 來創(chuàng)建一個 <Input> 標簽。

React.createElement(
 type,
 [props],
 [...children]
)

標簽上的屬性會作為 props 參數(shù)傳遞給 createElement 函數(shù)。

<Input onChange={this.toggleCheck}> 表示將組件中的 toggleCheck 方法賦值給 createElement 的入?yún)?props(props 是個對象,接收所有書寫在標簽上的屬性,),實際調(diào)用的時候一如上面所說的,調(diào)用的已經(jīng)不是組件中的 toggleCheck 方法了。

React.createElement(type, props){
 // 讓我們創(chuàng)建一個 <type> 并在 <type> 的值發(fā)生變化的時候調(diào)用一下 `props.onChange`
 ...
 props.onChange() // 它已經(jīng)不是原來的方法了,丟失了上下文
 ...
}

因為 ES6 的 Class 是在嚴格模式下執(zhí)行的,所以事件處理器中如果使用了 this 那它就是 undefined。

所以你看到 React 官方的示例中,constructor 里有 bind(this) 的語句就不奇怪了,就是為了糾正這個事件處理器歪了的執(zhí)行上下文。

 constructor() {
  super();
  this.state = {
   isChecked: false
  };
+ this.toggleCheck = this.toggleCheck.bind(this);
 }

這樣是能正常工作了,但是,這句代碼的存在真的很別扭,因為,

?對于業(yè)務(wù)來說,毫無意義,徒增代碼量
?很丑陋,每加一個處理器就要加一條這樣的綁定
?冗余,這樣重復的代碼大量冗余在項目中,在搜索中混淆了原本的方法

避免的方式有很多,就看哪種最對味。下面來看看如何避免寫這些綁定方法。

#0行內(nèi)的綁定

最簡單的可以在行內(nèi)進行綁定操作,這樣不用單獨寫一句出來。

  <input
      type="checkbox"
      checked={this.state.isChecked}
-       onChange={this.toggleCheck}
+      onChange={this.toggleCheck.bind(this)}
   />

#1箭頭函數(shù)

因為箭頭函數(shù)不會創(chuàng)建新的作用域,其上下文是語義上的(lexically)上下文。所以在綁定事件處理器時,直接使用剪頭函數(shù)是很方便的一種規(guī)避方法。

 <input
      type="checkbox"
      checked={this.state.isChecked}
-       onChange={this.toggleCheck}
+      onChange={() => this.toggleCheck()}
     />

#2將類的方法改成屬性

如果將這個處理器作為該組件的一個屬性,這個屬性作為事件的處理器以箭頭函數(shù)的形式存在,執(zhí)行的時候也是能正常獲取到上下文的。

- toggleCheck() {
+ toggleCheck = () => {
  this.setState(currentState => {
   return {
    isChecked: !currentState.isChecked
   };
  });
 }

看完上述內(nèi)容,你們對React 組件中怎么使用bind有進一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計公司行業(yè)資訊頻道,感謝大家的支持。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

分享題目:React組件中怎么使用bind-創(chuàng)新互聯(lián)
轉(zhuǎn)載來源:http://muchs.cn/article36/dsiesg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站排名、外貿(mào)建站云服務(wù)器、移動網(wǎng)站建設(shè)、網(wǎng)站建設(shè)域名注冊

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化