2017-06-05 81 views
4

React tutorial,它说为什么事件处理程序需要引用而不是调用?

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

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

不过,我不明白为什么那会是......任何人都可以澄清这对我好吗?为什么不能作为处理程序传递函数调用?

+0

'alert('click')'是一个函数调用。 React会读取它并立即执行它。您应该将引用传递给命名函数。所以,'this.myFunction'而不是'this.myFunction()'。或者,您可以引用一个匿名函数,这就是您在原始文章中输入的内容。 – glhrmv

回答

9

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

想要传递给onClick的是函数,而不是undefined

因此,你必须做的:onClick={myFunction}其中myFunction可以() => alert("...")正如你所说,或者您可以使用bind创建类似的功能:

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

bind一个新功能这将使用"click"参数在内部调用alert函数。


类似的情况是当你做setTimeout(() => alert("after 1 second"), 1000)setTimeout需要一个功能。如果你做setTimeout(alert("..."), 1000),确实会调用alert,但setTimeout将接收第一个参数undefined(这就是alert返回的结果)。

相反,如果你有返回功能,功能,将工作:

// 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 
+0

谢谢!你的回答和安德鲁的回答让我更清楚了! – coffeeak

+0

这是一个很好的答案,但如果它真的解释了为什么返回值被更详细地调用,这将是更好的选择,这是手头的问题。 – Li357

+0

@coffeeak酷!考虑标记其中一个答案:) –

4

当你有一个事件处理程序它必须是一个函数引用,而不是一个函数调用。这是因为在执行处理程序的内部,处理程序在被调用之前首先被评估为。使用内联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(),不好。因此,您必须传递函数引用,即对可调用函数的引用。

+0

谢谢!非常好的解释! – coffeeak

相关问题