如何将事件作为参数传递给JavaScript中的内联事件处理程序?


103
// this e works
document.getElementById("p").oncontextmenu = function(e) {
    e = e || window.event;
    var target = e.target || e.srcElement;
    console.log(target);
};

// this e is undefined
function doSomething(e) {
    e = e || window.event;
    var target = e.target || e.srcElement;
    console.log(target);
}
<p id="p" onclick="doSomething(e)">
    <a href="#">foo</a>
    <span>bar</span>
</p>

也有人提出过类似的问题。

但是在我的代码中,我试图获取被单击的子元素,例如aspan

那么event作为参数传递给事件处理程序的正确方法是什么,或者如何在处理程序内部获取事件而不传递参数呢?

编辑

我知道addEventListenerjQuery,请提供将事件传递给inline事件处理程序的解决方案。



5
使用内联事件处理程序而不是切换到addEventListener是否有充分的理由?en.wikipedia.org/wiki/Unobtrusive_JavaScript
Xotic750

2
@ Xotic750对我来说,例如,当通过ajax动态加载或重新加载html时,无需每次手动重新绑定它们。
Wadih M.

Answers:


166

传递event对象:

<p id="p" onclick="doSomething(event)">

获取被点击的孩子element(应与event参数一起使用:

function doSomething(e) {
    e = e || window.event;
    var target = e.target || e.srcElement;
    console.log(target);
}

传递element自身(DOMElement):

<p id="p" onclick="doThing(this)">

参见jsFiddle上的实时示例


11
(对于任何想知道的人:是的,即使某些[例如Firefox]没有全局event对象,它也可以在Chrome,Firefox等上运行。这是因为调用DOM0处理程序的上下文中有一个event对象,即使[在某些浏览器上],它也不是全球性的。)
TJ Crowder

this指的是p,但我试图得到aspan
user1643156

3
我知道,传递“事件”是唯一知道的方法,只要它得到支持即可。在这种情况下,解析“ this”是没有用的
Xotic750

5
@ user1643156这非常重要。该参数必须准确命名为“事件”
The-null-Pointer-

1
瓦迪(Wadih M.)的答案远胜于此。这一说法具有误导性(就像其他类似的东西一样),使人们认为,实际上,当JavaScript在被调用函数内部已经并可以使用“ event”参数时,应该在函数调用中放入“(事件)”参数,因此,无需声明它(花了我几天的时间才意识到,更改变量名没有什么区别,因为它实际上没有被传递)。此外,那里给出的解释也消除了对JS为什么如此工作的任何怀疑(也许不应该这样,但这不是我的判断……)
Cyber​​knight

15

由于内联事件作为函数执行,因此您可以简单地使用arguments

<p id="p" onclick="doSomething.apply(this, arguments)">

function doSomething(e) {
  if (!e) e = window.event;
  // 'e' is the event.
  // 'this' is the P element
}

接受的答案中提到的“事件”实际上是传递给函数的参数的名称。它与全球事件无关。


好提示。人们何时开始采用Web组件,call()并且apply()将证明在模拟主流js框架中可用的数据绑定功能方面至关重要。另外一个技巧是Object.assign(this.querySelector('my-btn'), this)在Web组件和数据绑定中执行类似的操作。您可以从内联事件访问父级Web组件类的任何方法onclick="toggleBtnActive.call(this, true)"
阿德里安·莫伊萨

8

您不需要通过,默认情况下this已经存在event自动传递的对象,该event.target对象包含其来源的对象。您可以简化语法:

这个:

<p onclick="doSomething()">

将与此一起工作:

function doSomething(){
  console.log(event);
  console.log(event.target);
}

您不需要实例化该event对象,它已经存在。试试看。并且event.target将包含调用它的整个对象,您之前将其称为“ this”。

现在,如果您从代码中的某个位置动态触发doSomething(),您将注意到它event是未定义的。这是因为它不是由单击事件触发的。因此,如果您仍想人为触发事件,只需使用dispatchEvent

document.getElementById('element').dispatchEvent(new CustomEvent("click", {'bubbles': true}));

然后doSomething()将看到eventevent.target照常!

无需传递到this任何地方,并且可以使函数签名免于布线信息并简化操作。


至少在IE11上不是这样,没有默认参数。
cskwg

1
@cskwg它也适用于IE11。它适用于所有主要浏览器,因为这是向后兼容所必需的。正如我在答案中提到的,只有从事件触发了javascript函数(这是唯一存在事件的情况),才会有一个已经称为“事件”的对象,您可以轻松地在函数内部访问它而不必将额外的布线传递给功能原型。我刚刚使用IE11在我的机器上针对onclick事件进行了测试,并且'event'变量包含一个“ PointerEvent对象”。
Wadih M.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.