为什么事件处理程序需要引用而不是调用?

时间:2017-06-05 14:17:10

标签: javascript reactjs

React tutorial中,它说

  

执行onClick={alert('click')}会立即发出警报,而不是点击按钮时。

class Square extends React.Component {
  render() {
    return (
      <button className="square" onClick={() => alert('click')}>
        {this.props.value}
      </button>
    );
  }
}

然而,我无法理解为什么会这样......有人可以为我澄清这个吗?为什么不能将函数调用作为处理程序传递?

2 个答案:

答案 0 :(得分:11)

执行onClick={alert("click")}时,将调用alert函数并将返回值(undefined)分配给onClick属性。那么,React看到的是onClick={undefined}并说:嗯,这不是一个函数,为什么我会添加这样的处理程序?

您希望传递给onClick的是一个函数,而不是undefined

因此,您必须执行:onClick={myFunction},如您所提及的,myFunction可以是() => alert("..."),或者您可以使用bind创建类似的功能:

onClick={alert.bind(window, "click")}

bind返回 新函数,它将在内部使用alert参数调用"click"函数。

类似的情况是setTimeout(() => alert("after 1 second"), 1000)setTimeout期望一个功能。如果您执行setTimeout(alert("..."), 1000),则会调用alert,但setTimeout将作为第一个参数undefined收到(这是alert返回的内容)。< / p>

相反,如果你有一个返回一个函数的函数,那么它将起作用:

// This will be called first and will return a function
const sayHelloTo = name => {
   // This will be the function passed to `setTimeout`
   return () => alert(`Hello ${name}`);
};
setTimeout(sayHelloTo("Alice"), 1000);

您可以以相同的方式使用onClick内容:

onClick={sayHelloTo("Alice")}

这是关于背景中发生的事情的一个非常小的例子(它只是一个概念证明,我确定它实际发生的事情比这更好):

const elm = {
  onClick: null,
  // The click method can be invoked manually
  // using `elm.click()` or is natively invoked by the browser
  click () {
     if (typeof this.onClick === "function") {
        this.onClick();
     }
  }
};

// If you do:
elm.onClick = alert("click"); // this calls the alert, and returns undefined
elm.onClick === undefined // true

// But when doing:
elm.onClick = () => alert("click");
typeof elm.onClick // "function"

elm.click(); // this will call the alert

答案 1 :(得分:4)

当你有一个事件处理程序时,它必须是一个函数引用,而不是一个函数调用。这是因为在内部执行处理程序时,处理程序首先被评估,然后才能被调用。使用内联JSX表达式(例如传递事件处理程序prop时),在调用处理程序之前,在声明组件时,表达式为 evaluate

因此,如果您传入alert('click')之类的调用,它将在评估时发出警报。当触发事件并调用处理程序时,它将尝试调用alert的返回值(未定义) - 不好。相反,您需要一个函数引用,在计算时会为您提供一个可调用函数,然后将其称为处理程序。

以此伪代码为例:

function on(event, handler) {
    //some event listener function that runs the handler when event happens
    //then we call handler when the event happens:
    handler();
}

想象一下,如果我们将函数调用为on('click', alert('test')),那么将评估alert('test')并且返回值将作为处理程序传递,这是未定义的。那你就试着打电话给undefined(),不好。因此,您必须传递函数引用,即对可调用函数的引用。