Событие щелчка jQuery не запускается в jQueryMobile
Используя jQuery jquery-1.9.1.js и jQueryMobile 1.3.1 (Chrome 26/Windows 7), я не могу понять, почему одно из этих событий "щелчка", связанное с #one1, срабатывает, а другое - нет:
HTML:
<div data-role="page" id="one" data-theme="a">
<div data-role="header" data-position="inline">
<h1>One</h1>
</div>
<div data-role="content" data-theme="a">
<a href="#" id="one1">[one]</a>
<a href="#two">two</a>
<a href="#three">three</a>
</div>
</div>
JavaScript:
<script>
$(document).on( "mobileinit", function() {
$(document).on('click', '#one1', function(e){
console.log('firing');
});
$('#one1').on("click", function() {
console.log('not firing');
});
});
</script>
Когда я запускаю его в JSFiddle, оба события запускаются, если они не включены в событие "mobileinit": http://jsfiddle.net/9NRwa/
Что мне здесь не хватает?
2 ответа
вступление
Во-первых, событие mobileinit не должно использоваться для привязки события. Хотя он МОЖЕТ использоваться таким образом, Mobileinit не был создан для этой цели. Он был создан для автоматической инициализации параметра jQuery Mobile, поэтому его не следует использовать для привязки событий.
Правильный путь - использовать правильные события страницы, такие как pageinit. Для получения дополнительной информации о событиях страницы взгляните на мой другой ответ, который охватывает различные события страницы jQuery Mobile и их отличие от обычной парадигмы готовности документа jQuery: jQuery Mobile: документ готов против событий страницы.
Не дай мне ответить на этот вопрос. Такие события, как щелчок, могут быть связаны несколькими различными способами. Давайте посмотрим на примеры, которые вы использовали:
Различные способы привязки событий с помощью jQuery
Первый пример
$(document).on('click', '#one1', function(e){
console.log('firing');
});
Этот первый пример является чем-то новым, что впервые стало использоваться с устаревшим методом live. По сути, это механизм делегирования событий, который позволяет привязывать обработчики событий не только ко всем существующим экземплярам данного типа узла, но также и к любым будущим экземплярам данного типа узла (под "типом" я подразумеваю набор узлов DOM, соответствующих данный селектор jQuery). Здесь я хочу сказать, что во время привязки событий этот элемент не должен существовать в DOM, в основном этот метод работает, связывая обработчики событий с самим документом, а затем реагируя на все события, возникающие в DOM. Поэтому не имеет значения, существует элемент #one1 или нет во время привязки события. Вы можете создать его динамически позже, и он все еще будет работать.
Второй пример
$('#one1').on("click", function() {
console.log('not firing');
});
Это на старом способе привязки событий. Это требует, чтобы событие существовало в DOM, прежде чем событие может быть связано. В вашем случае вы пытались привязать это событие click к элементу, который не существовал в DOM на тот момент. Неважно, что он был загружен после процесса привязки.
Рабочий пример
Пример jsFiddle: http://jsfiddle.net/Gajotres/QmNsa/
Посмотрите на этот пример. Там вы увидите 5 различных способов привязки событий клика в jQuery Mobile:
- Событие с 2 щелчками связывается в HEAD, перед тем как страница инициализируется в DOM
- 2 события клика связаны в HEAD в событии pagebeforeshow, в основном это также делегирование привязки, потому что событие связывается, когда страница собирается показываться и уже находится внутри DOM
- Событие с 1 кликом связывается в ТЕЛЕ после всего содержимого страницы. Поскольку в этот момент весь контент загружается внутри DOM, это событие нажатия будет работать.
HTML:
<!DOCTYPE html>
<html>
<head>
<title>jQM Complex Demo</title>
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; minimum-scale=1.0; user-scalable=no; target-densityDpi=device-dpi"/>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.css" />
<script src="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.js"></script>
<script>
$(document).on('click', '#one1', function(e){
// This example will work because it was bind with event delegation process
console.log('Firing 1');
});
$('#one1').on("click", function() {
// This example will not work because event do not exist in this moment
console.log('Not firing');
});
$(document).on( "pagebeforeshow", function() {
// This example will work because it was bind with event delegation process
$(document).on('click', '#one1', function(e){
console.log('Firing 2');
});
// This example will work because element exist in a DOM during the pagebeforeshow event
$('#one1').on("click", function() {
console.log('Firing 3');
});
});
</script>
</head>
<body>
<div data-role="page" id="index">
<div data-theme="b" data-role="header">
<h1>Index page</h1>
</div>
<div data-role="content">
<a href="#" id="one1" data-role="button">[one]</a>
</div>
</div>
<script>
$('#one1').on("click", function() {
// This example will work because we are binding it when element is already loaded into the DOM
console.log('Firing 4');
});
</script>
</body>
</html>
Заключение
- Не используйте событие mobileinit для привязки событий, оно будет срабатывать до загрузки страницы в DOM, и будут работать только события, связанные с делегированием.
- Свяжите свои события в правильных событиях на странице jQuery Mobile.
Полезные ссылки по этой теме:
jQuery Live () метод и передача событий
В то время как живой метод не рекомендуется использовать вместо метода. В некоторых тестах метод работает в 2 раза быстрее.
- Различные события на jQuery Mobile
- Что означает "пузыри событий"?
Как указано в документации:
Поскольку событие mobileinit запускается немедленно, вам необходимо привязать обработчик события перед загрузкой jQuery Mobile.
В настоящее время ваш mobileinit
событие запускается после загрузки jQuery Mobile, так как jsFiddle
выполнит ваш код JavaScript после завершения загрузки любых библиотек, выбранных вами на боковой панели. Чтобы это работало, ваша структура должна выглядеть так:
<script src="jQuery library include first"></script>
<script>
$(document).on("mobileinit", function() {
// Your code here
});
</script>
<script src="jQuery Mobile include last"></script>