Скрипты, запущенные в загруженных jquery.ajax () страницах, запускают document.ready слишком рано - PullRequest
6 голосов
/ 02 ноября 2010

Мой сайт использовал jquery.load() для навигации по большому фрагменту страницы. Я действительно ценю возможность включать только определенную часть загруженного контента, здесь div с id = "content":

$(frame_selector).load(url +" #content", function(response, status, xhr) {...});

Но теперь мне нужно иметь возможность запускать скрипты, которые являются частью динамически загружаемых страниц. Jquery.load() удаляет эти сценарии, а jquery.ajax() - нет. Поэтому я продублировал функцию частичного содержимого jquery.load в вызове ajax следующим образом:

$.ajax({
  url: url,
  dataType: 'html', 
  success: function(data, textStatus, XMLHttpRequest) {
      // Only include the response within the #content id element.
      $(frame_selector).html( jQuery("<div>")
            .append(data)
            .find("#content")
      );
  }
});

Проблема в том, что скрипты, которые динамически загружаются из вызова ajax, не работают надежно. Иногда они, кажется, не имеют никакого эффекта, возможно, потому что они бегут слишком рано. Сценарии просто выполняют DOM-манипуляции в jquery - не полагаясь на изображения, флэш-память или что-то, что еще не загружено. Чтобы не застрять, у меня есть этот отвратительный хак, чтобы все заработало. Вместо загруженного AJAX-скрипта просто используйте:

$(document).ready( function() {...} );  // unreliable

Я задерживаю сценарий за 200 мс до запуска:

$(document).ready( window.setTimeout( function() {...}, 200 )); // HATE THIS

Кто-нибудь знает, как я могу сделать это надежно, без жесткого кодирования задержки? Я предполагаю, что это условие гонки между <script> и моей логикой загрузки #content в новый div, но я не уверен, что с этим делать.

Ответы [ 2 ]

7 голосов
/ 02 ноября 2010

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

jQuery имеет свойство isReady, которое оно устанавливает после запуска на странице события ready.

Любые последующие вызовы jQuery.ready(...) сначала проверят этот флаг isReady. Если флаг установлен в true, он немедленно вызовет обработчик. Вы можете понять, почему это может вызвать проблемы в вашем коде.

Один из вариантов - загрузить ответ во фрагмент jQuery и проанализировать все теги <script /> для последующего выполнения.

var ajaxResponse = $(html);
var scripts = ajaxResponse.find('script');

// Move your scripts into a new element
var tempScripts = $().append(scripts);

// Append your content, followed by your script tags
$(document).append(ajaxResponse);
$(document).append(tempScripts);
1 голос
/ 02 ноября 2010

@ Дэн имеет ответ.При загрузке скриптов через ajax документ isReady имеет значение true.Это означает, что если это тег сценария, запрашиваемый вашим ajax-запросом:

<script type="text/javascript">
    if (jQuery.isReady) {
        $('body').append("<div id='new_content'>Document Ready</div>");
    }
    else {
        $('body').append("<div id='new_content'>Document Not Ready</div>");
    }
</script>

Вместо синтаксического анализа используйте JSON.Одно свойство будет содержать HTML.Другое свойство будет содержать скрипты.

Тогда вы можете сделать это:

$(document).append(ajaxResponse.html);
$(document).append(ajaxResponse.script);

Также, если вы загрузите скрипты с готовой функцией, окружающей ваш код, это создаст замыкание.это закрытие продлится всю жизнь страницы.Утечки памяти будут создаваться каждый раз, когда вы запрашиваете этот скрипт, не обновляя вашу страницу

...