ES6类 - 从事件处理程序中调用方法

时间:2017-07-07 12:06:41

标签: javascript ecmascript-6 es6-class

我正在尝试为我当前项目的交互式日历编写ES6课程。

该类看起来类似于以下内容:

class Calendar {

constructor (s) {

    this.eventButtons = s.eventButtons;
    this.eventButtons.forEach(button => button.addEventListener('click', this.method1);
    this.eventBoxes = s.eventBoxes;


method1 (e) {
    e.preventDefault();
    this.method2(e.target.href);
}

method2 (url) {
    console.log(url);
}

}


export default Calendar;

我知道'this'关键字的上下文已从构造函数更改为已在method1函数中单击的按钮。但是我不知道如何将按钮和构造函数的上下文保持在同一个函数中。我尝试将按钮事件侦听器代码更改为以下内容:

this.eventButtons.forEach(button => button.addEventListener('click', this.method1).bind(this);

但这只是将'this'关键字的上下文切换到构造函数而不是按钮。我需要在我的功能中使用它们。

有什么想法吗?我希望这是一个非常普遍的问题吗?

6 个答案:

答案 0 :(得分:7)

您可以创建一个发送事件和按钮的闭包。闭包将保持此上下文并发送按钮

button => button.addEventListener('click', event => this.method1(event, button))

答案 1 :(得分:5)

由于您使用的是ES6,您是否尝试使用arrow function

  

箭头函数表达式的语法短于函数   表达式并不绑定它自己的this,arguments,super或   new.target。这些函数表达式最适合非方法   函数,它们不能用作构造函数。

method1 = (e) => {
    e.preventDefault();
    this.method2(e.target.href);
}

答案 2 :(得分:3)

您有几个选择:

您可以自己绑定方法:

this.method1 = this.method1.bind(this);
this.method2 = this.method2.bind(this);

bind operator如果您正在使用Babel(或其他一些转录程序),则会{{3}}。它还没有被标准接受,所以我厌倦了使用它。使用bind运算符,您可以执行等效操作:

this.method1 = ::this.method1
this.method2 = ::this.method2

另一种选择是做你已经完成的事情,只是纠正了。

您必须绑定方法,而不是forEach的结果。

this.eventButtons.forEach(button =>
    button.addEventListener('click', this.method1.bind(this)));

或使用bind op:

this.eventButtons.forEach(button =>
    button.addEventListener('click', ::this.method1));

最后,您还可以选择使用箭头符号为词法范围创建包装函数:

this.eventButtons.forEach(button =>
    button.addEventListener('click', (...params) => this.method1(...params)));

答案 3 :(得分:3)

如果您使用ES6,您也可以使用for而不是forEach。这可以防止使用自己的范围创建另一个回调。在此代码中,关键字“this”仍然引用原始类。

this.eventButtons = s.eventButtons;
for(b of this.eventButtons){
   b.addEventListener('click', () => this.method1);
}

答案 4 :(得分:2)

尝试使用lambda表达式来设置事件的委托。如下所示:

class MainTable extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      results: []
    };
  }

  componentDidMount(){
    axios.get(this.props.link)
      .then(res => {
        this.setState({results: res.data.results});
    });
  }

  render() {
    return (
      <Table hover striped bordered responsive size="sm">
        <thead>
          <tr>
            <th>Name</th>
            <th>Name</th>
          </tr>
        </thead>
        <tbody>
          {this.state.results.map(result =>
            <tr key={result.fileId}>
              <td>{result.Name}</td>
              <td>{result.Name}</td>
            </tr>
          )}
        </tbody>
      </Table>
    );
  }
}

答案 5 :(得分:2)

您可以使用bind创建部分功能:

this.eventButtons.forEach(button => button.addEventListener('click', this.method1.bind(this, button));

假设您将method1更改为:

,则可以正常工作
method1 (button, e) {
  e.preventDefault();
  this.method2(e.target.href);
}