2017-05-31 73 views
2

在反應中動態更改事件綁定的建議/最乾淨的方式是什麼?如何在反應中重新綁定點擊事件

例如,如果我最初在handleFirstClick方法

handleFirstClick() { 
    //do other stuff 
    //rebind the button, so that next time it's clicked, handleSecondClick() would be called 
} 

有這樣

<button type="button" onClick={this.handleFirstClick}> 

一個按鈕,然後在情況下,它不是完全清楚我的意思,這裏就是想什麼我使用jQuery代替React

$('#myButton').on('click', handleFirstClick); 

function handleFirstClick() { 
    //other stuff 
    $('#myButton').off('click'); 
    $('#myButton').on('click', handleSecondClick); 
} 
+0

我不知道這是否是正確的方法,但我會對那個按鈕計算點擊次數的狀態,並且有'handleClick()'相應地調用合適的功能。 –

回答

1

解決方案1:反應狀態和Ternary Expressions

爲了改變事件的綁定,你需要在render方法中有一個if-else。爲組件創建一些狀態以處理按鈕是否已被點擊。第一次點擊後,設置狀態,以便將來運行第二個功能。您可以包含基本的ternary expression以檢查render()中的狀態。

class FancyButton extends React.Component { 
 
    constructor() { 
 
    super() 
 
    this.state = { 
 
     clicked: false 
 
    } 
 

 
    //Bindings for use in render() 
 
    this.onFirstClick = this.onFirstClick.bind(this) 
 
    this.onSecondClick = this.onSecondClick.bind(this) 
 
    } 
 

 
    onFirstClick() { 
 
    console.log("First click") 
 
    this.setState({ 
 
     clicked: true 
 
    }) 
 
    } 
 

 
    onSecondClick() { 
 
    console.log("Another click") 
 
    } 
 

 
    render() { 
 
    return (< 
 
     button onClick = { 
 
     this.state.clicked ? this.onSecondClick : this.onFirstClick 
 
     } > Click < /button> 
 
    ) 
 
    } 
 
} 
 

 
ReactDOM.render(< FancyButton/> , document.getElementById("root"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<div id="root"></div>

解決方法2:在一個對象的屬性

堅持國家在更一般的意義上,你可能不需要改變事件處理程序在你的渲染方法。如果您只調用一個onClick處理程序並切換對象屬性,則可以在每次點擊後跳過重新渲染反應組件(由於跳過this.setState)。

class FancyButton extends React.Component { 
 
    constructor() { 
 
    super() 
 
    this.clicked = false 
 

 
    //Bindings for use in render() 
 
    this.onClick = this.onClick.bind(this) 
 
    } 
 

 
    onClick() { 
 
    if (!this.clicked) { 
 
     this.onFirstClick() 
 
    } else { 
 
     this.onSecondClick() 
 
    } 
 
    this.clicked = true 
 
    } 
 

 
    onFirstClick() { 
 
    console.log("First click") 
 
    } 
 

 
    onSecondClick() { 
 
    console.log("Another click") 
 
    } 
 

 
    render() { 
 
    return (< 
 
     button onClick = { 
 
     this.onClick 
 
     } > Click < /button> 
 
    ) 
 
    } 
 
} 
 

 
ReactDOM.render(< FancyButton/> , document.getElementById("root"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<div id="root"></div>

我個人建議的第二個解決方案,因爲它是更有效的,但你可以在你自己的哪個適合您的情況最好的決定。

+0

儘管這並不能完全回答這個問題,但我認爲它是被接受的,因爲它很乾淨而且有效。這很可能是我的問題的答案是,「這不是你在做什麼反應」 – Jedediah

0

創建一個函數,該函數監視狀態並確定應該運行哪個函數。

handleClick() { 
    if (this.state.clickNumber === 1) { 
     this.handleFirstClick() 
    } elseif (this.state.clickNumber === 2) { 
     this.handleSecondClick() 
    } 
} 
handleFirstClick() { 
    //do stuff 
    this.setState({clickNumber: 2}) 
} 
handleSecondClick(){ 
    //do other stuff 

    // maybe increment click number again this.setState({clickNumber: 3}) 
} 
1

只需按住點擊按鈕的次數,然後使用它來指定處理程序。看到這個片段,

class App extends React.Component{ 
 
\t constructor(props){ 
 
\t \t super(props) 
 
\t \t this.state={ 
 
\t \t \t clicked: 0 
 
\t \t } 
 
\t } 
 
\t firstClick(){ 
 
\t \t console.log("first click") 
 
\t \t this.setState({clicked: 1}) 
 
\t } 
 
\t afterClick(){ 
 
\t \t console.log("more clicks") 
 
\t } 
 

 
\t render(){ 
 
\t \t return(
 
\t \t \t <div><button onClick={this.state.clicked === 0 ? this.firstClick.bind(this) : this.afterClick.bind(this)}>Click me</button> 
 
\t \t \t </div> 
 
\t \t) 
 
\t } 
 
} 
 

 
ReactDOM.render(<App />, document.getElementById("app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<div id="app"></div>

1

你可以使用一個閉合。

const createClickHandler =() => { 
    const firstClickHandler =() => {} 
    const secondClickHandler =() => {} 
    let clicked = false 

    return() => { 
    if (clicked) return secondClickHandler() 
    clicked = true 
    firstClickHandler() 
    } 
} 
0

在React中,您最好使用狀態來管理這些事件。您可以將狀態和操作保存在單個按鈕組件中,也可以保存在呈現按鈕組件的父組件中。

在設置這個按鈕組件時,利用了一個二進制狀態,用一個布爾值來點擊一個和兩個函數。這也可以通過修改按鈕的handleClick或者繼續迭代到附加函數 - 或者甚至每次點擊更新輸入(取決於您的用例)調用相同的函數,從而輕鬆更改爲函數two並保持在那裏。

在這個例子中,我決定展示如何在精簡的React App中工作。在這個例子中,你會注意到我保持每個按鈕的狀態。有人懷疑另一個組件是否需要跟蹤點擊次數,因此這是遵循將狀態推向最低可能組件的反應原則。在這種情況下,我允許父組件保存將按鈕狀態作用的函數。我沒有看到這些函數中的必要性,它們的開銷也與每個按鈕組件重複,但按鈕組件本身也可以調用函數本身。

我添加了兩個按鈕來顯示他們將如何單獨維護他們的狀態。原諒註釋塊格式,它不會在代碼片段窗口外顯示。

/** 
 
\t * \t \t @desc Sub-component that renders a button 
 
\t * \t \t @returns {HTML} Button 
 
\t */ 
 
class BoundButton extends React.Component { 
 
    constructor(props) { 
 
    super(props); 
 
    this.handleClick = this.handleClick.bind(this); 
 

 
    this.state = ({ 
 
     //toggled in this example to keep click state 
 
     click2: false, 
 
    }); 
 
    } 
 
    
 
    handleClick(e) { 
 
    //calls parent method with the clicked button element and click state 
 
    this.props.click(e.nativeEvent.toElement, this.state.click2); 
 
    
 
    //toggles click state 
 
    this.setState({ click2: !this.state.click2 }); 
 
    } 
 

 
    render() { 
 
    
 
    return (
 
     <button 
 
     id = {this.props.id} 
 
     name = {this.props.name} 
 
     className = {this.props.className} 
 
     onClick = {this.handleClick} > 
 
     Click Here {this.state.click2 ? '2' : '1'}! 
 
     </button>   
 
    ); 
 
    } 
 
    
 
} 
 

 

 

 
/** 
 
\t * \t \t @desc Component that creates and binds button sub-components 
 
\t * \t \t @returns {HTML} Bound buttons 
 
\t */ 
 
class BindExample extends React.Component { 
 
    constructor(props) { 
 
    super(props); 
 
    this.handleButtonClick = this.handleButtonClick.bind(this); 
 
    this.clickAction1 = this.clickAction1.bind(this); 
 
    this.clickAction2 = this.clickAction2.bind(this); 
 

 
    this.state = ({ 
 
     //state vars 
 
    }); 
 
    } 
 
    
 
    clickAction1(el) { 
 
    console.log('Action 1 on el: ', el); 
 
    } 
 
    
 
    clickAction2(el) { 
 
    console.log('Action 2 on el: ', el); 
 
    } 
 
    
 
    handleButtonClick(el, click2) { 
 

 
    console.log('click!'); 
 
    
 
    if (click2) this.clickAction2(el); 
 
    else this.clickAction1(el); 
 
    } 
 
    
 
    render() { 
 
    
 
    return (
 
     <div> 
 
     <BoundButton 
 
      id='ex-btn1' 
 
      name='bound-button-1' 
 
      className='bound-button' 
 
      click={this.handleButtonClick} /> 
 
     <BoundButton 
 
      id='ex-btn2' 
 
      name='bound-button-2' 
 
      className='bound-button' 
 
      click={this.handleButtonClick} /> 
 
     </div> 
 
    ); 
 
    } 
 
    
 
} 
 

 
/** 
 
\t * \t \t @desc React Class renders full page. Would have more components in a 
 
    *  real app. 
 
\t * \t \t @returns {HTML} full app 
 
\t */ 
 
class App extends React.Component { 
 
    render() { 
 
    return (
 
     <div className='pg'> 
 
     <BindExample /> 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

 

 
/** 
 
\t * \t \t Render App to DOM 
 
\t */ 
 

 
/** 
 
\t * \t \t @desc ReactDOM renders app to HTML root node 
 
\t * \t \t @returns {DOM} full page 
 
\t */ 
 
ReactDOM.render(
 
    <App/>, document.getElementById('root') 
 
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 

 
<div id="root"> 
 
    <!-- This div's content will be managed by React. --> 
 
</div>

+0

我想知道爲什麼有人會投我的答案,我剛剛花了一個小時寫一個原始解決方案,當你跑步?我認爲這是一個堅實的答案,而沒有評論的推動式投票則是無益的。 –

相關問題