$(документ.)на Click handler и стандартный click handler ведут себя по-разному на iOS

Я обычно связываю обработчики кликов с помощью формы,

$(document).on('click', 'element', function() { ... });

чтобы избежать проблем с элементами, которые загружаются позже. Это было правильно на настольных браузерах (и Chrome, эмулирующий iPhone), но на реальном iPhone это не работало (и я попытался решений какcursor: pointer;')

Я заметил, что другая кнопка работает, используя стандартный обработчик click. Я изменил свою новую кнопку, чтобы использовать

$('element').click(function() { ... });

и это начать работать. Почему эти два метода применения обработчика кликов работают по-разному в iOS?

2 ответов


Я посмотрел на исходный код jquery ,и они одинаковы (оба .click и on('click') используйте ту же функцию, которая является .on.

.нажмите

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 если нет аргументов, которые не являются вашим случаем)


Я думаю, что это происходит из-за задержки 300ms для мобильных браузеров.

согласно Google:

...мобильные браузеры будут ждать приблизительно 300ms от времени, которое нажмите кнопку, чтобы запустить событие click. Причина этого что браузер ждет, чтобы увидеть, действительно ли вы выполняете двойное нажатие.

я столкнулся с той же проблемой для одного из моих клиентских проектов, и для этого я использовал https://github.com/ftlabs/fastclick библиотека для устранения задержки 300 мс между физическим нажатием и запуском события щелчка в мобильных браузерах.

вы также можете попробовать https://github.com/dave1010/jquery-fast-click

в том же проекте я также столкнулся с проблемой двойного нажатия для выпадающих меню, и это также было связано с задержкой 300ms.

проблема двойного нажатия появлялась в браузерах/устройствах 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

Это может быть полезным для вас.

редактировать

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

это возможно потому, что большинство событий DOM пузырь вверх по дереву от точки происхождения. Если вы нажмете на элемент #id, будет создано событие click, которое будет пузыриться через все элементы предка (Примечание: На самом деле перед этим есть фаза, называемая "фазой захвата", когда наступает событие вниз по дереву к цели). Вы можете запечатлеть событие на любом из этих предков.

второй пример связывает обработчик событий непосредственно к элементу. Событие по-прежнему будет пузыриться (если вы не предотвратите это в обработчике), но поскольку обработчик привязан к цели, вы не увидите эффектов этого процесса.

делегируя обработчик событий, вы можете гарантировать, что он выполняется для элементов, которые не существовали в DOM во время привязки. Если ваш элемент #id был созданный после вашего второго примера, ваш обработчик никогда не будет выполняться. Путем привязки к элементу, который, как вы знаете, определенно находится в DOM во время выполнения, вы гарантируете, что ваш обработчик действительно будет прикреплен к чему-то и может быть выполнен позже.

Это, вероятно, не работает из-за одного из:

  • не используя последнюю версию jQuery
  • не обертывание кода внутри DOM ready
  • или вы делаете что-то, что заставляет событие не всплывать до слушателя в документе.

для захвата событий на элементах, которые создаются после объявление прослушивателей событий-вы должны привязаться к родительскому элементу или элементу выше в иерархии.

например:

$(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