【问题标题】:Scripts running in jquery.ajax() loaded pages run document.ready too early在 jquery.ajax() 加载页面中运行的脚本运行 document.ready 过早
【发布时间】:2010-11-01 23:26:00
【问题描述】:

我的网站使用jquery.load() 在页面的很大一部分上进行导航。我真的很欣赏只包含加载内容的特定部分的能力,这里是 id="content" 的 div:

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

但现在我需要能够运行作为动态加载页面一部分的脚本。 Jquery.load() 删除了这些脚本,但 jquery.ajax() 没有。因此,我在 ajax 调用中复制了 jquery.load 的部分内容功能:

$.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 调用动态加载的脚本运行不可靠。有时它们似乎没有任何效果,也许是因为它们运行得太早了。这些脚本只是在 jquery 中进行 DOM 操作——不依赖于图像或闪存或任何不应该加载的东西。为了不被卡住,我有这个可怕的黑客来让事情正常进行。而不是只使用 AJAX 加载的脚本:

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

我在运行前将脚本延迟了 200 毫秒:

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

有人知道我怎样才能在不延迟硬编码的情况下可靠地完成这项工作吗?我猜这是&lt;script&gt; 和我将#content 加载到新div 中的逻辑之间的竞争条件,但我不知道该怎么做。

【问题讨论】:

  • 可以同步请求捕获数据。
  • 这是一个可怕的想法。在执行同步请求时,您的浏览器 UI 将被锁定。

标签: jquery jquery-load


【解决方案1】:

我假设脚本正在对您通过 AJAX 添加的 DOM 元素进行操作。

jQuery 有一个isReady 属性,一旦在页面上触发了ready 事件,它就会设置该属性。

随后对jQuery.ready(...) 的任何调用都将首先检查此isReady 标志。如果标志设置为 true,它将立即调用处理程序。您可以看到为什么这会导致您的代码出现问题。

一种选择是将响应加载到 jQuery 片段中并解析出所有 &lt;script /&gt; 标记以供稍后执行。

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);

【讨论】:

  • 这对我不起作用。问题似乎是 .find() 找不到脚本...
【解决方案2】:

@Dan 有答案。通过 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);

此外,如果您使用代码周围的 ready 函数加载脚本,它将创建一个闭包。此关闭将持续页面的生命周期。每次您请求该脚本而不刷新页面时,都会创建内存泄漏

【讨论】:

    猜你喜欢
    • 2014-11-21
    • 2012-10-24
    • 2017-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-26
    • 2019-01-23
    相关资源
    最近更新 更多