如何在 onclick 函数中保留‘ this’引用的同时,通过编程从锚标记调用 onclick()事件?

下面的代码不起作用... (至少在 Firefox 中不起作用: document.getElementById('linkid').click()不是一个函数)

<script type="text/javascript">
function doOnClick() {
document.getElementById('linkid').click();
//Should alert('/testlocation');
}
</script>
<a id="linkid" href="/testlocation" onclick="alert(this.href);">Testlink</a>
252019 次浏览

To trigger an event you basically just call the event handler for that element. Slight change from your code.

var a = document.getElementById("element");
var evnt = a["onclick"];


if (typeof(evnt) == "function") {
evnt.call(a);
}

If you're using this purely to reference the function in the onclick attribute, this seems like a very bad idea. Inline events are a bad idea in general.

I would suggest the following:

function addEvent(elm, evType, fn, useCapture) {
if (elm.addEventListener) {
elm.addEventListener(evType, fn, useCapture);
return true;
}
else if (elm.attachEvent) {
var r = elm.attachEvent('on' + evType, fn);
return r;
}
else {
elm['on' + evType] = fn;
}
}


handler = function(){
showHref(el);
}


showHref = function(el) {
alert(el.href);
}


var el = document.getElementById('linkid');


addEvent(el, 'click', handler);

If you want to call the same function from other javascript code, simulating a click to call the function is not the best way. Consider:

function doOnClick() {
showHref(document.getElementById('linkid'));
}

You need to apply the event handler in the context of that element:

var elem = document.getElementById("linkid");
if (typeof elem.onclick == "function") {
elem.onclick.apply(elem);
}

Otherwise this would reference the context the above code is executed in.

The best way to solve this is to use Vanilla JS, but if you are already using jQuery, there´s a very easy solution:

<script type="text/javascript">
function doOnClick() {
$('#linkid').click();
}
</script>
<a id="linkid" href="/testlocation" onclick="alert(this.href);">Testlink</a>

Tested in IE8-10, Chrome, Firefox.

In general I would recommend against calling the event handlers 'manually'.

  • It's unclear what gets executed because of multiple registered listeners
  • Danger to get into a recursive and infinite event-loop (click A triggering Click B, triggering click A, etc.)
  • Redundant updates to the DOM
  • Hard to distinguish actual changes in the view caused by the user from changes made as initialisation code (which should be run only once).

Better is to figure out what exactly you want to have happen, put that in a function and call that manually AND register it as event listener.

$("#linkid").trigger("click");

Have a look at the handleEvent method
https://developer.mozilla.org/en-US/docs/Web/API/EventListener

"Raw" Javascript:

function MyObj() {
this.abc = "ABC";
}
MyObj.prototype.handleEvent = function(e) {
console.log("caught event: "+e.type);
console.log(this.abc);
}


var myObj = new MyObj();


document.querySelector("#myElement").addEventListener('click', myObj);

Now click on your element (with id "myElement") and it should print the following in the console:

caught event: click
ABC

This allows you to have an object method as event handler, and have access to all the object properties in that method.

You can't just pass a method of an object to addEventListener directly (like that: element.addEventListener('click',myObj.myMethod);) and expect myMethod to act as if I was normally called on the object. I am guessing that any function passed to addEventListener is somehow copied instead of being referenced. For example, if you pass an event listener function reference to addEventListener (in the form of a variable) then unset this reference, the event listener is still executed when events are caught.

Another (less elegant) workaround to pass a method as event listener and stil this and still have access to object properties within the event listener would be something like that:

// see above for definition of MyObj


var myObj = new MyObj();


document.querySelector("#myElement").addEventListener('click', myObj.handleEvent.bind(myObj));

Granted, OP stated very similarly that this didn't work, but it did for me. Based on the notes in my source, it seems it was implemented around the time, or after, OP's post. Perhaps it's more standard now.

document.getElementsByName('MyElementsName')[0].click();

In my case, my button didn't have an ID. If your element has an id, preferably use the following (untested).

document.getElementById('MyElementsId').click();

I originally tried this method and it didn't work. After Googling I came back and realized my element was by name, and didn't have an ID. Double check you're calling the right attribute.

Source: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click

Old thread, but the question is still relevant, so...

(1) The example in your question now DOES work in Firefox. However in addition to calling the event handler (which displays an alert), it ALSO clicks on the link, causing navigation (once the alert is dismissed).

(2) To JUST call the event handler (without triggering navigation) merely replace:

document.getElementById('linkid').click();

with

document.getElementById('linkid').onclick();