Как я могу программно вызвать событие onclick () из тега привязки, сохранив ссылку this в функции onclick?


83

Следующее не работает ... (по крайней мере, не в 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>

Ответы:


110

Вам нужен applyобработчик событий в контексте этого элемента:

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

В противном случае thisбудет ссылаться на контекст, в котором выполняется приведенный выше код.


3
Я думаю, что вы единственный, кто не считает меня дураком (за то, что не упомянул обозначение скобок / несовместимость браузера onclick | click). Пятно!
Ropstah

3
рассмотрите это: howtocreate.co.uk/tutorials/javascript/domevents - вызовет ли функция onclick все зарегистрированные обработчики событий? Кроме того, ложный вызов события не приведет к действию по умолчанию, связанному с этим событием (например, отправка формы).
jrharshath

Гамбо, поскольку этот код действительно дает разные результаты, он по-прежнему не работает с библиотеками Microsoft.Ajax и Microsoft.AjaxMvc ....
Ропста,

1
Зачем использовать apply()здесь? Вы можете просто сделать elem.onclick();, и elemэто будет ссылка в функции - просто!
Doin

19

Лучший способ решить эту проблему - использовать Vanilla JS, но если вы уже используете jQuery, есть очень простое решение:

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

Протестировано в IE8-10, Chrome, Firefox.


3
почему голос против? прокомментируйте причину, чтобы я мог улучшить свой вопрос, если вы считаете, что что-то не так.
luschn

1
в stackoverflow указано, что вы не должны предоставлять ответы, которые зависят от внешнего ресурса (например, библиотеки, такой как jQuery), если OP явно не упомянул об этом в вопросе, я думаю, что это было причиной
отрицательного

еще в 2013 году все использовали jquery - но в настоящее время я согласен :) - но я сохраню ответ для справок в будущем.
luschn

15

Чтобы вызвать событие, вы просто вызываете обработчик событий для этого элемента. Небольшое изменение в вашем коде.

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

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

1
+1. Кроме того, небольшой поиск в Google показывает, что foo.click () - это только IE, конечно, я могу ошибаться ...
karim79

1
Вам следует использовать точечную нотацию (.onclick), а не скобку (["onclick"]).
Радд Зволински

.onclick () или .click () работают не так, как ожидалось. В Firefox .click (или в скобках ['click']) это «НЕ ФУНКЦИЯ». Но при вызове .onclick () вы теряете ссылку «this» (мне это нужно в ASP.NET MVC, потому что информация из тега <a> требуется в выполняющейся функции)
Ropstah

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

2
Добро пожаловать в SO. Не могли бы вы подробнее рассказать, почему это работает (что именно делает и т. Д.) И чем это отличается от других решений?
m00am

2
зачем отмечать этот ответ? это лучшее решение на этой странице, если вы используете jquery ... one liner - не победить!
PodTech.io

1
Ответ не должен требовать jQuery
Грег Перхэм

5

Конечно, OP очень похожим образом заявил, что это не сработало, но для меня это сработало. Судя по заметкам в моем источнике, похоже, что это было реализовано примерно во время или после публикации OP. Возможно, сейчас это более стандартно.

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

В моем случае у моей кнопки не было идентификатора. Если у вашего элемента есть идентификатор, желательно использовать следующий (непроверенный).

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

Первоначально я пробовал этот метод, но он не сработал. После поиска в Google я вернулся и понял, что мой элемент был назван по имени и не имел идентификатора. Дважды проверьте, что вы вызываете правильный атрибут.

Источник: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click


1

Взгляните на метод handleEvent
https://developer.mozilla.org/en-US/docs/Web/API/EventListener

"Необработанный" 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);

Теперь щелкните свой элемент (с идентификатором «myElement»), и он должен напечатать в консоли следующее:

пойманное событие: нажмите
ABC

Это позволяет использовать метод объекта в качестве обработчика событий и иметь доступ ко всем свойствам объекта в этом методе.

Вы не можете просто передать метод объекта в addEventListener напрямую (вот так:) element.addEventListener('click',myObj.myMethod);и ожидать, что он myMethodбудет действовать так, как если бы меня обычно вызывали для объекта. Я предполагаю, что любая функция, переданная в addEventListener, каким-то образом копируется, а не упоминается. Например, если вы передадите ссылку на функцию прослушивателя событий в addEventListener (в форме переменной), а затем отключите эту ссылку, прослушиватель событий по-прежнему будет выполняться при обнаружении событий.

Другой (менее элегантный) обходной путь для передачи метода в качестве прослушивателя событий и стиля thisи при сохранении доступа к свойствам объекта в прослушивателе событий будет примерно таким:

// see above for definition of MyObj

var myObj = new MyObj();

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

1

Старая ветка, но вопрос все еще актуален, так что ...

(1) Пример в вашем вопросе теперь ДЕЙСТВИТЕЛЬНО работает в Firefox. Однако помимо вызова обработчика событий (который отображает предупреждение), он ТАКЖЕ щелкает ссылку, вызывая навигацию (после закрытия предупреждения).

(2) Чтобы ПРОСТО вызвать обработчик событий (без запуска навигации), просто замените:

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

с участием

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

0

Если вы используете это исключительно для ссылки на функцию в атрибуте onclick, это кажется очень плохой идеей. Встроенные события - вообще плохая идея.

Я бы посоветовал следующее:

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);

Если вы хотите вызвать ту же функцию из другого кода javascript, имитация щелчка для вызова функции - не лучший способ. Рассматривать:

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

это о сохранении ссылки на «это». Я не могу создать только часть onclick в привязке (.NET MVC). Мне нужно создать полный тег привязки. Этот тег полностью требуется для функции onclick (например, он использует атрибут href).
Ropstah

-1

В общем, я бы не рекомендовал вызывать обработчики событий «вручную».

  • Непонятно, что выполняется из-за нескольких зарегистрированных слушателей
  • Опасность попадания в рекурсивный и бесконечный цикл событий (щелчок A запускает щелчок B, запускает щелчок A и т. Д.)
  • Избыточные обновления DOM
  • Трудно отличить фактические изменения в представлении, вызванные пользователем, от изменений, внесенных в качестве кода инициализации (который следует запускать только один раз).

Лучше выяснить, что именно вы хотите, чтобы произошло, поместите это в функцию и вызовите ее вручную И зарегистрируйте ее как прослушиватель событий.


ОП спрашивает, как что-то сделать, а не как лучше что-то делать. Это не CodeReview. Если бы вы ответили на его вопрос, а затем заявили об отказе от ответственности, все было бы иначе.
Тайлер Монтни
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.