在 jquery.ajax() 加载的页面中运行的脚本运行 document.ready 太早

发布于 2024-09-30 08:51:46 字数 1171 浏览 3 评论 0原文

我的网站使用 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 操作——不依赖图像或 flash 或任何不应该加载的东西。为了避免陷入困境,我使用了这个可怕的技巧来让事情正常运转。而不是仅使用 AJAX 加载的脚本:

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

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

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

有人知道如何在不硬编码延迟的情况下可靠地工作吗?我猜测这是

My site was using jquery.load() to do navigation on a big chunk of the page. I really appreciate the ability to only include only a particular part of the loaded content, here the div with id="content":

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

But now I need to be able to run scripts that are part of the pages being loaded dynamically. Jquery.load() strips out these scripts, but jquery.ajax() doesn't. So I duplicated the partial-content functionality of jquery.load in an ajax call as such:

$.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")
      );
  }
});

The problem is that the scripts which are being dynamically loaded from the ajax call aren't running reliably. Sometimes they don't seem to have any effect, perhaps because they're running too early. The scripts are just doing DOM manipulation in jquery -- not relying on images or flash or anything that's not supposed to be loaded yet. To keep from getting stuck I have this hideous hack to get things working. Instead of the AJAX-loaded script just using:

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

I delay the script 200ms before running:

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

Anybody know how I can make this work reliably without hard-coding a delay? I'm guessing it's a race condition between the <script> and my logic to load #content into a new div, but I'm not sure what to do about it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦里°也失望 2024-10-07 08:51:46

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

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

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

一种选择是将响应加载到 jQuery 片段中并解析出所有

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

I assume the scripts are doing manipulation upon the DOM elements you're adding through AJAX.

jQuery has an isReady property that it sets once the ready event has been triggered on the page.

Any subsequent calls to jQuery.ready(...) will first check this isReady flag. If the flag is set to true, it will call the handler immediately. You can see why this would cause problems in your code.

One option would be to load the response into a jQuery fragment and parse out all of the <script /> tags for execution later.

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);
§普罗旺斯的薰衣草 2024-10-07 08:51:46

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

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

@Dan has the answer. When loading scripts via ajax the document isReady is true. This means if this is the script tag that is requested by your ajax request:

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

Instead of parsing utilize JSON. One property will hold HTML. Another property will hold the scripts.

Then you can do this:

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

Also if you load scripts with the ready function surrounding you code it will create a closure. this closure will last the lifetime of the page. Memory leaks will be created every time you request that script without refreshing your page

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文