Когда выполняется только обратный вызов $(document).ready?

Предположим, что мы привязываем .click() к тегу привязки (<a>) в $(document).ready обратный вызов. Этот обработчик отменяет действие по умолчанию (после href) и показывает предупреждение.

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

Вот несколько HTML-страниц, содержащих якорь, но порядок включения скриптов отличается. Какая разница (если есть) между ними? Будут ли разные браузеры вести себя по-другому?

Page1:

<html>
<head>
    <title>Test 1</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
    <script type="text/javascript">
    $(function() {
        $('a').click(function() {
            alert('overriding the default action');
            return false;
        });
    });
    </script>
</head>
<body>
    <a href="#" onclick="location.href='http://www.google.com'; return false;">Test</a>
</body>
</html>

Стр .2:

<html>
<head>
    <title>Test 1</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
</head>
<body>
    <a href="#" onclick="location.href='http://www.google.com'; return false;">Test</a>
    <script type="text/javascript">
    $(function() {
        $('a').click(function() {
            alert('overriding the default action');
            return false;
        });
    });
    </script>
</body>
</html>

Page3:

<html>
<head>
    <title>Test 1</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
    <a href="#" onclick="location.href='http://www.google.com'; return false;">Test</a>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
    <script type="text/javascript">
    $(function() {
        $('a').click(function() {
            alert('overriding the default action');
            return false;
        });
    });
    </script>
</body>
</html>

Итак, возможно ли, что пользователь перенаправляется на href, нажав на якорь и никогда не увидит предупреждение (игнорируя, конечно, случай, когда JavaScript отключен, конечно)? Может ли это произойти в любом из приведенных мной примеров?

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

Что произойдет, если HTML будет быстро сгенерирован веб-сервером, но библиотека jquery займет время, которое нужно извлечь с удаленного сервера? Это повлияет на мой сценарий? Каков порядок включения сценариев по сравнению с загрузкой DOM? Могут ли они выполняться параллельно?

Ответ 1

Пример 3 будет иметь наибольшую вероятность, что пользователь сможет щелкнуть ссылку без того, что обработчик еще не присоединился. Поскольку вы загружаете библиотеку jQuery после визуализации ссылки, если серверы Google немного медленнее (или поиск в DNS занимает секунду или около того), или компьютер пользователя медленно обрабатывает jQuery, ссылка не будет иметь обработчик кликов когда пользователь пытается щелкнуть его.

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

  • Загрузите jQuery в head (пример 1 или 2)
  • Прикрепите событие click сразу после элемента <a>, но не в обратном вызове DOMReady. Таким образом, он будет вызываться немедленно и не будет ждать остальной части документа.

После визуализации элемента он может быть схвачен из DOM, а затем jQuery может получить к нему доступ:

<a href="http://www.google.com">Test</a>
<script type="text/javascript>
    // No (document).ready is needed. The element is availible
    $('a').click(function() {
        alert('overriding the default action');
        return false;
    });
</script>

Кроме того, построение комментария user384915, если действие полностью зависит от JavaScript, тогда даже не отрисуйте его как часть HTML, добавьте его после готовности jQuery:

<script type="text/javascript">
jQuery(function($){
   $("<a />", { 
      style: "cursor: pointer", 
      click: function() {
        alert('overriding the default action');
        return false;
      },
      text: "Test"
   }).prependTo("body");
});
</script>

Ответ 2

Здесь у вас есть несколько разных вопросов.

Когда именно $(document).ready выполняется обратный вызов?

Выполняется, как только DOM полностью загружен. НЕ, когда все (например, изображения) закончены, загрузка будет выглядеть как .load(). Это (в общем) до этого, в основном это когда страница сама построена.

Что я хотел бы знать, когда точно обратный вызов выполнит

Когда он нажимается.

можно щелкнуть пользователем на якоре (документ был показано в браузере), но событие еще не прикреплен.

Да, это возможно. Но положив его в .ready(), дайте вам наилучший шанс, что он не будет. Есть только два способа сделать это "более уверенным", чего не будет. На самом деле они используют "onclick" в своей ссылке и помещают javascript непосредственно после ссылки (а не в .ready()), поэтому она выполняется сразу после создания ссылки.

Кроме того, нет никакой разницы между тем, как будут работать 2 примера кода, которые вы предоставили. Однако во втором случае вам не нужно вводить код в .ready(), потому что он существует после ссылки, он всегда будет выполняться после создания ссылки. Если вы удалите его из .ready(), это будет первый из двух способов, описанных выше.

Кроме того, вместо "return false"; в вашем обратном вызове лучше использовать .preventDefault() и .stopPropagation(), это позволит вам указать, хотите ли вы предотвратить действие по умолчанию или остановить событие от пузырьков, или и то, и другое.

Ответ 3

Это зависит от многих вещей. Например, если вы кодировали кодировку, возможно, что пользователь получит кусок, но поскольку документ еще не готов, слушатель не будет прикреплен.

Событие готовности jQuery - это событие DOMContentLoaded в браузерах, совместимых с W3C (стандартизованный в спецификации HTML5) и некоторые альтернативы этого в других (например, readistate в IE).

DOMContentLoaded (MDC)

Уволен на странице Объект документа при анализе документа законченный. К тому времени, когда это событие огонь, страница DOM готова.

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

Но как Питер Мишо указал в свою статью из-за различий в том, как браузеры реализуют это событие " надежную технику для раннего оживления невозможно в больших четырех браузерах.

Итак, я бы сказал, что вы не можете полагаться на 100% на событие jQuery ready, но в большинстве случаев оно будет работать просто отлично.

Ответ 4

В YUI существуют методы onContentReady() и onAvailable(). к сожалению, в jQuery нет эквивалента. Однако есть плагин, вдохновленный ими:

http://www.thunderguy.com/semicolon/2007/08/14/elementready-jquery-plugin/

Это должно позволить вам привязать события к якорю до полной загрузки DOM.

Ответ 5

Ваш третий пример дает максимальную возможность щелчка пользователя без привязки обработчика переопределения. Браузер обычно загружает и анализирует каждый <script>, прежде чем переходить к следующему. Вы загружаете jQuery из внешнего источника (Google), который, хотя и может быть надежно, может быть недоступен или медленный для загрузки. У вас есть оба блока <script> в конце вашего документа <body>, поэтому предыдущие области страницы, вероятно, уже были загружены и отображены на экран, пока эти два последних скрипта будут обработаны. Несмотря на то, что этот подход призван представить пользователю отзывчивый опыт загрузки страниц, они могут щелкнуть в течение этого неопределенного периода времени, и, конечно, обработчик переопределения еще не был присоединен.

Здесь интересная статья YUIblog о сценариях и порядок загрузки здесь.

Ответ 6

Конечно, можно "обмануть" предупреждение (даже если Javascript включен). Попробуйте перетащить ссылку в поле url, и вы увидите, что она будет выполнена без этого предупреждения. Это особенно проблематично, если ссылка запускает действие удаления.

О обратном вызове document.ready. У меня тоже такая проблема. Позволь мне объяснить. Мы делаем проект, в котором отображаются все формы во всплывающих окнах (окно jQuery). Поэтому, когда всплывающее окно закрыто (на данный момент), страница перезагружается, и у меня были случаи, когда я перенаправляюсь на другой экран, а не открываю новое всплывающее окно.

В полной мере согласен с user384915 о том, как разместить javascript непосредственно в событии onClick или даже лучше для href-тега.