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

IT技术 javascript reactjs
2021-04-01 03:19:47

React 教程中,它说

DoingonClick={alert('click')}会立即发出警报,而不是在单击按钮时发出警报。

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

但是,我不明白为什么会这样......有人可以为我澄清一下吗?为什么不能将函数调用作为处理程序传递?

2个回答

当您这样做时onClick={alert("click")},将调用该alert函数并将返回值 ( undefined)分配给该onClick属性。所以,React 看到的是onClick={undefined}并说:好吧,那不是一个函数,我为什么要添加这样的处理程序?

您要传递给的onClick是一个函数,而不是undefined.

因此,您必须这样做:onClick={myFunction}wheremyFunction可以() => alert("...")像您提到的那样,或者您可以使用它bind来创建类似的功能:

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

bind返回一个新函数,该alert函数将在内部使用"click"参数调用该函数


类似的情况是当您执行setTimeout(() => alert("after 1 second"), 1000). setTimeout期待一个功能。如果你这样做setTimeout(alert("..."), 1000)alert,实际上将被调用,但setTimeout将作为第一个参数接收undefined(这就是alert返回的内容)。

相反,如果您有一个返回 function 的函数,那将起作用:

// 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
这是一个很好的答案,但如果它实际上解释了为什么更详细地调用返回值的原因会更好,这是手头的问题。
2021-05-28 03:19:47
@AndrewLi 谢谢,试图让它更清楚一点。:)
2021-05-30 03:19:47
@coffeeak 酷!考虑标记答案之一:)
2021-05-31 03:19:47
谢谢!你的回答和安德鲁的回答让我现在更清楚了!
2021-06-08 03:19:47

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

因此,如果您传入诸如 之类的调用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(),不好。因此,您必须传递一个函数引用,一个对可调用函数的引用。

谢谢!很好的解释了!
2021-05-29 03:19:47