TL; DR
В современном браузере:
<input type="button" id="someButton" value="Some Button">
<script>
document.getElementById("someButton").addEventListener("click", function() {
alert("Hello");
}, false);
</script>
Обратите внимание, что скрипт после кнопки в HTML. Почему это имеет значение? Продолжайте читать.
document.getElementById("someButton").addEventListener("click", function() {
snippet.log("Hello");
}, false);
<input type="button" id="someButton" value="Some Button">
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
О, хорошо, ты продолжал читать.
Есть три части:
Когда подключать обработчик (часть, для которой используется код jQuery ready
)
Как найти элемент (ы) для подключения (часть, для которой используется код jQuery $("#someButton")
)
Как подключить обработчик (часть, для которой он используется click
)
Когда подключать обработчик
При обработке событий непосредственно в элементе вы не можете подключить обработчик событий, пока элемент не существует. Имея дело с элементами, которые находятся в основном HTML страницы, вы знаете, что они существуют после того, как их HTML был проанализирован. Так, например:
<div>...</div>
<script>
// Here, we know that that div exists
</script>
Поэтому, если у вас нет веских причин поступить иначе, поместите теги сценария для вашего кода JavaScript в конец документа, непосредственно перед закрывающим тегом </body>
. Тогда вы знаете, что все вышеперечисленные элементы (включая document.body
) существуют.
Если у вас нет другого выбора, кроме как поместить теги сценария в другое место (например, анти-шаблон, который помещает их в <head>
), тогда вам придется прибегнуть к подключению обработчика событий, когда содержимое страницы было разобран. Стандартным является DOMContentLoaded
, к которому вы подключаетесь document
. К сожалению, IE8 и более ранние версии не поддерживают его, поэтому jQuery обеспечивает обратный вызов ready
. Вы также можете использовать событие load
для объекта window
, но оно не срабатывает до тех пор, пока long после анализа элементов страницы не будет, потому что он ожидает загрузки всех внешних ресурсов (все изображения и т. д.) до стрельбы.
Как найти элемент (ы) для подключения
В вашем примере элемент имеет значение id
, поэтому вы можете использовать document.getElementById
для его получения; который возвращает ссылку на объект элемента, или null
, если его нет с этим id
.
Современные браузеры, а также IE8 поддерживают document.querySelector
, который найдет первый элемент, соответствующий любому селектору CSS. Так, например, document.querySelector('div')
находит первый div
в документе, если он есть (null
, если его нет). document.querySelector('div.foo table tr.bar')
находит первый tr
элемент с классом bar
, который находится внутри table
, который находится внутри div
элемента с классом foo
.
Современные браузеры (и IE8) также предоставляют document.querySelectorAll
, что дает вам список (набор) всех элементов, соответствующих селектору CSS.
querySelector
и querySelectorAll
также доступны для элементов; когда вы используете их для элементов, они смотрят только на потомков этого элемента.
Существуют также различные другие функции, такие как getElementsByTagName
(поддерживается почти повсеместно, даже в старых IE), getElementsByName
(с использованием атрибута name
; у меня есть понятия не имею, насколько широко поддерживается), getElementsByClassName
(поиск по одному классу CSS; в IE8 и более ранних версиях его нет) и некоторых других.
Как подключить обработчик
Современные браузеры, включая IE9 и выше в стандартном режиме, поддерживают addEventListener
. В IE8 и более ранних версиях вы должны использовать оригинальный Microsoft attachEvent
(предшествующий addEventListener
).
theElement.addEventListener("click", function() {
// ...your handler code here
}, false);
// or
theElement.attachEvent("onclick", function() {
// ...your handler code here
});
Обратите внимание, что addEventListener
просто использует имя события ("click"
), но attachEvent
использует "on"
плюс имя события ("onclick")
. Также обратите внимание, что addEventListener
имеет третий аргумент, который вы почти всегда хочу установить значение false
. (В последних браузерах этот аргумент был необязательным, но это не всегда, поэтому, если вам может потребоваться поддержка старых, включите его.)
Основное преимущество использования addEventListener
или attachEvent
состоит в том, что при этом эти действия хорошо сочетаются с другими, поскольку элемент может иметь более одного обработчика , зарегистрированного для одного и того же события при использовании этих методов.
Элементы также предоставляют свойства, которым вы можете назначить функции, где имя свойства - on
, за которым следует имя события, например onclick
:
theElement.onclick = function() {
// Your handler code
};
Это поддерживается универсально кросс-браузерно,но проблема в том, что к элементу может быть подключен только один обработчик.
Итак, мы можем реализовать ваш код jQuery следующим образом:
<script>
document.getElementById("someButton").onclick = function() {
alert("Hello");
};
</script>
</body>
</html>
(Обратите внимание, где находится этот тег.) Но это не очень хорошо с другими.
document.getElementById("someButton").onclick = function() {
snippet.log("Hello");
};
<input type="button" id="someButton" value="Some Button">
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Или в современном браузере:
<script>
document.getElementById("someButton").addEventListener("click", function() {
alert("Hello");
}, false);
</script>
</body>
</html>
document.getElementById("someButton").addEventListener("click", function() {
snippet.log("Hello");
}, false);
<input type="button" id="someButton" value="Some Button">
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Или на IE8 и более ранних версиях:
<script>
document.getElementById("someButton").attachEvent("onclick", function() {
alert("Hello");
});
</script>
</body>
</html>
document.getElementById("someButton").attachEvent("onclick", function() {
snippet.log("Hello");
});
<input type="button" id="someButton" value="Some Button">
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Теперь предположим, что мы используем querySelectorAll
или подобное и получаем список элементов вместо одного элемента?Как мы можем подключить обработчик к каждому из них?
Мы можем использовать приемы из этого другого ответа , чтобы перебрать коллекцию, так как она будет подобной массиву объект (но не фактический массив).Скажем, мы хотим найти обработчик для всех div
элементов с классом foo
:
var list = document.querySelectorAll("div.foo");
Array.prototype.forEach.call(list, function(element) {
element.addEventListener("click", handler, false);
});
function handler() {
this.innerHTML = "You clicked me";
}
(Не беспокойтесь об этом this
, я расскажу об этом в "Подробнееисследовать "ниже.)
var list = document.querySelectorAll("div.foo");
Array.prototype.forEach.call(list, function(element) {
element.addEventListener("click", handler, false);
});
function handler() {
this.innerHTML = "You clicked me";
}
<div class="foo">foo</div>
<div class="foo">foo</div>
<div class="foo">foo</div>
<div class="foo">foo</div>
<div class="bar">bar (no handler)</div>
<div class="bar">bar (no handler)</div>
<div class="bar">bar (no handler)</div>
<div class="bar">bar (no handler)</div>
Дополнительные сведения
Обработка событий - это не только получение события.Иногда обработчики событий иногда хотят сделать:
Получить информацию о событии (например, если клавиша была нажата, какая клавиша?)
Запрет действия по умолчанию для события, если оно есть (например, предотвращение по умолчанию в событии submit
в форме останавливает его отправку)
Остановить распространение (всплывающее) событие на элементы контейнера
Ссылка на элемент, к которому подключено событие (чтобы мы могли использовать один и тот же обработчик для нескольких элементов)
# 4 легко: на обработчике, связанном с любым из механизмов, которые мы обсуждали выше, внутри обработчика, this
будет ссылаться на элемент, к которому было подключено событие.(Это не относится к соединениям атрибутов HTML, например, <div onclick="handler()">
, что является одной из многих причин не использовать их.) Если вы сделали что-то еще с this
(что вы можете), вы также можете получить доступ кэлемент, к которому вы подключили событие через свойство currentTarget
объекта события (подробнее ниже).
К сожалению, способ сделать это отличается в IE8 и более ранних версиях attachEvent
и в браузерах, соответствующих стандартам.(addEventListener
).Вот функция hookEvent
(которую я изначально написал для этого другого ответа ), которая позволяет использовать стандартизированный способ даже в старом IE:
var hookEvent = (function() {
var div;
// The function we use on standard-compliant browsers
function standardHookEvent(element, eventName, handler) {
element.addEventListener(eventName, handler, false);
return element;
}
// The function we use on browsers with the previous Microsoft-specific mechanism
function oldIEHookEvent(element, eventName, handler) {
element.attachEvent("on" + eventName, function(e) {
e = e || window.event;
e.preventDefault = oldIEPreventDefault;
e.stopPropagation = oldIEStopPropagation;
handler.call(element, e);
});
return element;
}
// Polyfill for preventDefault on old IE
function oldIEPreventDefault() {
this.returnValue = false;
}
// Polyfill for stopPropagation on old IE
function oldIEStopPropagation() {
this.cancelBubble = true;
}
// Return the appropriate function; we don't rely on document.body
// here just in case someone wants to use this within the head
div = document.createElement('div');
if (div.addEventListener) {
div = undefined;
return standardHookEvent;
}
if (div.attachEvent) {
div = undefined;
return oldIEHookEvent;
}
throw "Neither modern event mechanism (addEventListener nor attachEvent) is supported by this browser.";
})();
Использование hookEvent
мы можем сделать три вещи, перечисленные ранее, стандартным способом:
Мы получаем объект события в качестве первого аргумента функции-обработчика, что означает, что мы можем использовать его currentTarget
чтобы получить ссылку на элемент, к которому мы подключили событие, или target
, чтобы получить ссылку на элемент, из которого произошло событие, и т. Д.
Мы можем предотвратитьпо умолчанию, вызывая функцию preventDefault
объекта события
Мы можем остановить распространение, вызывая функцию stopPropagation
объекта события
Мы можем использоватьthis
(или event.currentTarget
) для ссылки на элемент, где мы перехватили событие
hookEvent
не является всесторонней, поющей, все танцующей функцией подключения события. (Во-первых, я никогда не заботился о поддержке un перехвата событий с ним.) Это пример кода, в основном.
Справочный материал
Большая часть этого теперь покрыта спецификацией HTML5, что намного больше, чем HTML
Различные аспекты определены DOM; список спецификаций здесь , текущий DOM4
Mozilla Developer Network имеет огромный диапазон достаточно точных референсных материалов (в отличие от некоторых других мета-сайтов, которые часто имеют проблемы с точностью).