$ (document).onx обработчик кликов и стандартный обработчик кликов ведут себя по-разному на iOS
Я обычно связываю обработчики кликов с помощью формы,
$(document).on('click', 'element', function() { ... });
чтобы избежать проблем с загрузкой элементов позже. Это корректно работало на настольных браузерах (и Chrome emulating iPhone), но на реальном iPhone это не сработало (и я попробовал решения, например 'cursor: pointer;
')
Я заметил, что работает другая кнопка, используя стандартный обработчик кликов. Я изменил свою новую кнопку, чтобы использовать
$('element').click(function() { ... });
и он начал работать. Почему эти два метода применения обработчика кликов работают по-разному на iOS?
Ответы
Ответ 1
Я посмотрел исходный код jquery, и они одинаковы (оба .click
и on('click')
используют ту же функцию, что и .on
.
.click
jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
"change select submit keydown keypress keyup contextmenu" ).split( " " ),
function( i, name ) {
// Handle event binding
jQuery.fn[ name ] = function( data, fn ) {
return arguments.length > 0 ?
this.on( name, null, data, fn ) :
this.trigger( name );
};
} );
как вы можете видеть, $.click
в конечном итоге вызовет .on
(или .trigger
, если нет аргументов, которые не являются вашим случаем)
Ответ 2
Я думаю, что это происходит из-за задержки в 300 мс для мобильных браузеров.
Согласно Google:
... мобильные браузеры будут ждать примерно 300 мс с момента, когда вы нажимаете кнопку, чтобы запустить событие click. Причиной этого является что браузер ожидает, действительно ли вы выполняете двойное нажатие.
Я столкнулся с одной и той же проблемой для одного из моих клиентских проектов, и для этого я использовал https://github.com/ftlabs/fastclick библиотеку для устранения задержки 300 мс между физическим нажмите и включите событие клика в мобильных браузерах.
Вы также можете попробовать https://github.com/dave1010/jquery-fast-click
В том же проекте я также столкнулся с проблемой двойного касания для выпадающих меню, а также из-за задержки в 300 мс.
Проблема с двойным нажатием появлялась в браузерах/устройствах Android, поэтому я обнаружил пользовательский агент и применил специальную функцию для обработки этой проблемы, которая может быть вам полезна.
<?php
if (user_agent() == 'android') {
$handleClick = "onclick=\"checkClicks('$base_url/index.php')\"";
$homePage = "#";
} else {
$handleClick = " ";
$homePage = "index.php";
}
?>
<!--//Script to Handle menu for mobile devices-->
<script type="text/javascript">
//handle 300ms delay click in android devices
var clicks = 0;
function checkClicks(e) {
clicks = clicks + 1;
if (clicks == 2) {
window.location = e;
} else {
//do nothing
}
}
</script>
Вы также можете попробовать некоторые доступные плагины, чтобы справиться с этой проблемой, если вы сталкиваетесь.
https://github.com/dachcom-digital/jquery-doubleTapToGo
https://github.com/zenopopovici/DoubleTapToGo
Это может быть полезно и вам.
Edited
Обработчик события привязан к элементу, расположенному выше дерева DOM (в данном случае, к документу) и будет выполняться, когда событие достигнет этого элемента, возникшего на элементе, соответствующем селектору.
Это возможно, потому что большинство событий DOM пузыряют дерево из точки происхождения. Если вы нажмете на элемент #id, генерируется событие клика, которое будет всплывать через все элементы-предки (примечание стороны: на самом деле есть фаза до этого, называемая "фазой захвата", когда событие спускается по дереву к цели). Вы можете зафиксировать событие для любого из этих предков.
Второй пример привязывает обработчик события непосредственно к элементу. Событие по-прежнему будет пузыриться (если вы не предотвратите это в обработчике), но поскольку обработчик привязан к цели, вы не увидите эффектов этого процесса.
Делегируя обработчик событий, вы можете убедиться, что он выполняется для элементов, которые не существовали в DOM во время привязки. Если ваш #id-элемент был создан после второго примера, ваш обработчик никогда не выполнит. Связываясь с элементом, который, как вы знаете, определенно находится в DOM во время выполнения, вы гарантируете, что ваш обработчик фактически будет привязан к чему-то и может быть выполнен по мере необходимости позже.
Вероятно, он не работает из-за одного из:
- Не использовать последнюю версию jQuery
- Не заверяйте свой код внутри готового документа DOM
- или вы делаете что-то, что заставляет событие не пузыриться до слушателя в документе.
Чтобы захватить события на элементах, которые создаются ПОСЛЕ объявления ваших прослушивателей событий, вы должны привязать к родительскому элементу или элементу выше в иерархии.
Например:
$(document).ready(function() {
// This WILL work because we are listening on the 'document',
// for a click on an element with an ID of #test-element
$(document).on("click","#test-element",function() {
alert("click bound to document listening for #test-element");
});
// This will NOT work because there is no '#test-element' ... yet
$("#test-element").on("click",function() {
alert("click bound directly to #test-element");
});
// Create the dynamic element '#test-element'
$('body').append('<div id="test-element">Click mee</div>');
});
В этом примере будет срабатывать только предупреждение "привязано к документу".
JSFiddle с jQuery 1.9.1