.on () не работает для динамически генерируемого контента

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

$(document).ready(function() {
  $('body').on('click', '.mainNav', function() {
    var href = $(this).attr('href');
    $('body').load(href);
   });
});

Это фрагмент кода, который вызывает у меня проблемы. По сути, предполагается, что он должен получить атрибут href из div, а затем загрузить его, чтобы заменить текущее содержимое тега body.

Это работает в первый раз, но когда новый контент создается через .load (), div перестает отвечать. Я новичок в JS, поэтому заранее прошу прощения, если ответ очевиден. Я пытался найти решение самостоятельно, но все, что я нахожу, говорит мне, что .on () должен работать для динамически генерируемого контента.

РЕДАКТИРОВАТЬ: не могу эмулировать проблему в скрипте, поэтому я отправляю pastebin со всей страницей индекса в надежде, что это прояснит проблему.

http://pastebin.com/xT5syd9j

РЕДАКТИРОВАТЬ: Он работает с использованием решения adeneo. Весьма признателен всем за их вклад и извинения за то, что не опубликовали все с самого начала. Думаю, это сэкономило бы время всем.


person CSED    schedule 04.08.2012    source источник
comment
.load основан на Ajax, что означает, что href могут быть только URL-адресами, основанными на том же домене, что и сценарий. Это называется политикой одинакового происхождения. Может быть, href это http://google.com. Это нарушит сценарий.   -  person Jonas G. Drange    schedule 05.08.2012
comment
Если вы не получаете ошибок на странице, это должно работать.   -  person PeeHaa    schedule 05.08.2012
comment
@PeeHaa, вы используете метод html(), а не метод load(). Это другое дело, так что это не доказательство.   -  person ErikE    schedule 05.08.2012
comment
@CSED: Есть ли у вас <script> теги для загрузки внешнего JS внутри <body>? В частности, загружаете ли вы таким образом сам jQuery? Если это так, переместите jQuery внутрь <head>, и проблема должна быть исправлена.   -  person Jon    schedule 05.08.2012
comment
@Jon: Внутри тела нет тегов скрипта. Все в голове. Сейчас я делаю скрипку с такой надеждой, что сможет преодолеть барьер моей ужасности в объяснениях.   -  person CSED    schedule 05.08.2012
comment
Что обычно содержится в атрибуте href?   -  person Purag    schedule 05.08.2012
comment
@Purmou: Извините, не видел комментария. Атрибут href содержит относительную ссылку на страницу, поэтому href = test.php. Ссылка действующая и проверенная.   -  person CSED    schedule 05.08.2012
comment
Ссылка НЕ ​​действительна, это div для гидроразрыва с атрибутом href!   -  person adeneo    schedule 05.08.2012
comment
К вашему сведению, в StackOverflow вы НЕ должны редактировать свой заголовок, чтобы включить РЕШЕНИЕ. Установленная вами зеленая галочка указывает всем, что у вас есть решение.   -  person jfriend00    schedule 05.08.2012
comment
Ах. Я тогда сниму. Спасибо что подметил это.   -  person CSED    schedule 05.08.2012


Ответы (3)


Не совсем уверен, в чем проблема, но я предполагаю, что это как-то связано с загрузкой в ​​тот же элемент, к которому прикреплен обработчик, поэтому попробуйте:

$(document).ready(function() {
    $(document).on('click', '.mainNav', function(e) {
        e.preventDefault();
        console.log('I just clicked : '+e.target.href);
        $('body').load(e.target.href);
    });
});

Кроме того, вы, конечно, знаете, что это заменит ВСЕ содержимое на вашей странице, и если в загруженном содержимом не будет нового элемента с тем же классом, ничего не произойдет. Я бы также предложил использовать контейнер для загрузки контента. И, конечно же, ссылки должны быть на реальные файлы на вашем сервере.

Также убедитесь, что в загружаемых файлах нет другого набора тегов <head>, <body> и т. Д., Так как это все испортит для вас, только содержимое HTML!

РЕДАКТИРОВАТЬ:

Если .mainNav является элементом типа <a href="link_you_are_trying_to_load"></a>, вам также необходимо предотвратить действие по умолчанию, см. Обновленный код.

НОВОЕ ИЗМЕНЕНИЕ:

Проблема, с которой вы столкнулись, довольно очевидна, вы используете такие элементы, как:

<div class="mainNav" href="test.php" id="active">

элемент div не имеет атрибута href, поэтому JS не получит это значение, поскольку он не является допустимым атрибутом ни для чего, кроме элемента <a>

Вы можете изменить свой элемент на элемент <a> или изменить атрибут href на:

<div class="mainNav" data-href="test.php" id="active">

и делать:

var href = $(this).data('href');

по крайней мере, это был бы правильный HTML!

Кроме того, у вас, похоже, есть «контейнерный» элемент с именем #site, так почему бы вам не сделать:

$('#site').load(href); //using the data-href as above
person adeneo    schedule 04.08.2012
comment
Я предполагаю, что это как-то связано с загрузкой в ​​тот же элемент, к которому прикреплен обработчик - ›Не имеет значения - person PeeHaa; 05.08.2012
comment
@ErikE: И я согласен с PeeHaa. Почему это имеет значение? Важно то, что в документации указано, что заменяется content элемента, а не сам элемент. Я действительно пробовал вариант на этой самой странице, и консоль JS выдает мне ошибки, которые намекают на то, что jQuery выгружается после первого вызова .load. - person Jon; 05.08.2012
comment
Это не должно иметь к этому никакого отношения, но произошли странные вещи, и в этих нескольких строках кода нечего отлаживать, либо href неправильный, либо что-то происходит с функцией load (). - person adeneo; 05.08.2012
comment
Это не работает. Div сейчас вообще не реагирует на щелчок. Href действителен, проверил. И файл, на который он указывает, не имеет тегов head или body. Он начинается с первого div после тела. Я постараюсь переделать все это на скрипке, так как у меня такое чувство, что это может быть случай, когда я что-то плохо объясняю. Дайте мне несколько минут и спасибо за быстрые ответы. - person CSED; 05.08.2012
comment
@CSED. Я просто добавил console.log к своему ответу, попробуйте использовать его и проверьте консоль браузера, чтобы узнать, что происходит, когда вы щелкаете элементы, и какой href вы получите обратно. Обычный JS href часто включает имя домена, тогда как jQuery обычно получает href, указанный в HTML и т. Д., Но, по крайней мере, это покажет вам, что ссылки действительно работают. - person adeneo; 05.08.2012
comment
Не могу поверить, что совсем забыл о preventDefault(). ›.‹ Это до боли очевидное решение здесь ... - person Purag; 05.08.2012
comment
@adeneo: Используя ваш код, консоль сообщает, что ссылка не определена, что является странным, поскольку при использовании инструментов chrome dev ссылка оказывается действительной, когда я нажимаю на нее. - person CSED; 05.08.2012
comment
@CSED - См. Мой обновленный ответ, вы не можете и не должны использовать атрибуты href с любым другим элементом, кроме <a> - person adeneo; 05.08.2012
comment
@adeneo #site - это просто контейнерный div для #mainContainer, это также первый div на странице href, на которую ссылаются. Я не знал, что у других элементов, кроме a, не должно быть атрибута href. Я попробую ваше решение и сообщу об этом. Я думал, что это могло быть так, но href в div фактически работал для первой ссылки до того, как содержимое было изменено с помощью load, поэтому я предположил, что div может иметь атрибут href. Однако это могло быть просто обработкой ошибок в браузере. - person CSED; 05.08.2012
comment
Да, вы можете прикрепить атрибут href к любому элементу, и в большинстве новых браузеров он будет работать, но он недействителен, и в большинстве случаев он не будет работать с javascript, и даже если это так, вы просите о проблемах. - person adeneo; 05.08.2012
comment
@Jon Хорошо, теперь я с тобой согласен. Документы, в которых говорится, что элемент не заменяется, а только его содержимое, ошибались. Он не должен потерять свой обработчик кликов. - person ErikE; 05.08.2012
comment
@adeneo: Работает. Я здесь почти плачу от радости. Проблема заключалась в том, что я глупо использовал атрибут href, надо было просто опубликовать все с самого начала. Много бы прояснил. Большое спасибо за помощь. - person CSED; 05.08.2012

Проблема здесь может заключаться в том, что вы действительно загружаете при вызове $('body').load(href). Если вы загружаете HTML-код всей страницы (включая теги <html> и <body>), у вас могут возникнуть проблемы. Ваш браузер работает с такими проблемами, делая что-то пригодное для использования из неправильного HTML (в вашем случае это что-то вроде <html><body><html><body>...</body></html></body></html>), что может дать неожиданные результаты.

Лучше всего:

  1. Правильно организуйте HTML (см. Ниже)
  2. Загружайте только часть сгенерированного выше HTML, когда вы загружаете его с помощью $(...).load().

Ad.1. Убедитесь, что у вас есть элемент чуть ниже тега <body>, который имеет собственный идентификатор и содержит все, что может быть расположено в теге <body>. Это может выглядеть так:

<html>
...
<body>
    <div id="main_div">
    <!-- all elements here -->
    </div>
</body>
</html>

Ad.2. Загрузить такой контент намного проще, так как вы можете добавить селектор к URL-адресу, переданному в .load() (см. «Загрузка фрагментов страницы» на jQuery .load() страница документов):

$('body').load(href + ' #main_div');

Таким образом вы получите страницу целиком, но получите только элемент с идентификатором «#main_div» и замените им весь <body> контент.

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

person Tadeck    schedule 05.08.2012
comment
Нет необходимости добавлять другой элемент внутрь body. - person Purag; 05.08.2012
comment
@Purmou: Вы правы, но хорошо, если код организован таким образом, если он должен так работать. Выбор элемента по идентификатору намного быстрее, чем при использовании, например. body > * предложенный вами селектор. По возможности следует выбирать элементы только по их идентификаторам (если это не является разумным). - person Tadeck; 05.08.2012
comment
@Tadeck: страница, которую я пытаюсь загрузить, не содержит тегов html / head / body. Структура в точности такая, как вы указали, div, содержащий все, что я хочу заменить, поэтому, когда я заменяю содержимое body, я заменяю большой div. Я думаю, это то, что вы пытались указать как возможную проблему. - person CSED; 05.08.2012
comment
@CSED: Итак, вы говорите, что страница, которую браузер извлекает с сервера, уже обрезана только до этого элемента. А как насчет тегов <script>? Есть ли в нем какие-нибудь? А как насчет элементов, которые не отвечают: есть ли у них собственные атрибуты onclick (и т. Д.)? И еще одно: вы уверены, что используете .on(), а не .one()? Потому что это многое прояснило бы;) - person Tadeck; 05.08.2012
comment
@Tadeck: нет тегов скрипта, однако решение adeneo работало. Проблема заключалась в моем идиотском использовании атрибута href. Тем не менее, спасибо за весь вклад. - person CSED; 05.08.2012
comment
@CSED: Довольно неожиданно;) Но поскольку его ответ помог, я думаю, вы должны принять его. Хорошо, что вы нашли решение. - person Tadeck; 05.08.2012

Попробуй это:

$(document).ready(function(){
    $('body').on('click', '.mainNav', function() {
        var href = $(this).attr('href');
        $('body').load(href + " body > *");
    });
});

Здесь мы загружаем только содержимое основного элемента на странице (href). Нет необходимости добавлять дополнительные элементы на эту страницу. Просто выберите содержимое тела, как упомянул Tradeck.

Проблема, очевидно, в том, что если страница в href является полной HTML-страницей, вы загружаете DOCTYPE, второй тег html, второй тег head и body и т. Д.

person Purag    schedule 05.08.2012
comment
Это именно то, что я предложил, за исключением элемента с отдельным идентификатором. Однако это должно сработать. - person Tadeck; 05.08.2012
comment
@Tadeck: Да, моя проблема - я не загрузил новые ответы, пока писал свои собственные. : P Хотя у нас здесь очень разные варианты, так что я думаю, что у нас все в порядке. :) - person Purag; 05.08.2012
comment
У меня нет проблем с этим. Я просто сказал, что он должен работать так же хорошо, как и мой собственный ответ;) Ваш ответ не требует изменения HTML страницы, мой предлагает такие изменения и работает быстрее. В любом случае, не удаляйте свои собственные, это добавляет ценности. - person Tadeck; 05.08.2012
comment
@Purmou: Не знал об этом, спасибо. Но это не имеет большого значения, поскольку страница, загружаемая через href, не содержит тега body, только div, который также содержит исходная страница, поэтому содержимое body заменяется с использованием полной страницы из ссылки href, не тело. Спасибо хоть. - person CSED; 05.08.2012