Javascript 触发 $document.ready(所以我无法修改的 AJAX 代码被执行)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2238030/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 23:24:34  来源:igfitidea点击:

Trigger $document.ready (so AJAX code I can't modify is executed)

javascriptjqueryajax

提问by kikito

My requirements are the following:

我的要求如下:

  • I've got a rich webpage that at a certain moment loads a bunch of HTML in a div, via AJAX.
  • The HTML I retrieve does have javascript (<script>...</script>)
  • The retrieved javascript contains $('document').ready( ... )parts
  • I can notmodify the retrieved javascript; it comes from an external lib
  • I've got a javascript function that is called when the AJAX is loaded. I'm trying to "trick it" into executing by doing:

    function AjaxLoaded() {
      $('document').trigger('ready');
    }
    
  • 我有一个丰富的网页,它在某个时刻div通过 AJAX加载了一堆 HTML 。
  • 我检索的 HTML 确实有 javascript ( <script>...</script>)
  • 检索到的 javascript 包含$('document').ready( ... )部分
  • 无法修改检索到的 javascript;它来自外部库
  • 我有一个在加载 AJAX 时调用的 javascript 函数。我试图通过执行以下操作来“欺骗”它:

    function AjaxLoaded() {
      $('document').trigger('ready');
    }
    

That doesn't cut it, I'm afraid.

恐怕这并不能解决问题。

I've seen severalresponseson Stack Overflow that "evade" this question by changing the code that is returned on the AJAX (make it a function and call it after loading, or just remove the $(document).ready()). I need to stress out that I can't change the retrieved code on this case.

我在 Stack Overflow 上看到过一些响应,它们通过更改 AJAX 上返回的代码来“逃避”这个问题(使其成为一个函数并在加载后调用它,或者只是删除$(document).ready())。我需要强调的是,在这种情况下,我无法更改检索到的代码。

采纳答案by John Boker

Afer some research i created a way to get it to work.

经过一些研究,我创造了一种让它发挥作用的方法。

here is my test that shows it working: http://www.antiyes.com/test/test2.php

这是我的测试,表明它可以正常工作:http: //www.antiyes.com/test/test2.php

here is the relevant code:

这是相关代码:

<script>
    // easy copy of an array
    Array.prototype.copy = function() {
        return [].concat(this);
    };

    // this function is added to jQuery, it allows access to the readylist
    // it works for jQuery 1.3.2, it might break on future versions
    $.getReadyList = function() {
        if(this.readyList != null)
            this.myreadylist =  this.readyList.copy();      
        return this.myreadylist;
    };

    $(document).ready(function() {
        alert("blah");
    });

</script>

<script>

    // this should be added last so it gets all the ready event
    $(document).ready(function() {
        readylist = $.getReadyList();
    });

</script>

then in the body I have:

然后在我的身体里:

<input type="button" onclick="$(readylist).each(function(){this();});" value="trigger ready" />

basically what i did was add a function to jQuery that copies the readyList before it's cleared out, then it will be available to be used by you.

基本上我所做的是向 jQuery 添加一个函数,该函数在清除 readyList 之前复制它,然后您就可以使用它了。

it looks like the code below doesnt work:

看起来下面的代码不起作用:

function AjaxLoaded() {
    $(document).trigger('ready');
}

drop the quotes around document.

去掉周围的引号document

回答by rakaloof

Since the jQuery readyList is not exposed as of version 1.4 (discussed here) the nice solutions above are broken.

由于 jQuery readyList 在 1.4 版(在此处讨论)未公开,因此上面的好解决方案已被破坏。

A way around this is by creating your own readyList, through overriding the original jQuery-ready method. This needs to be done before other scripts that use the original ready method are loaded. Otherwise just the same code as John/Kikito:

解决这个问题的一种方法是通过覆盖原始的 jQuery-ready 方法来创建您自己的 readyList。这需要在加载其他使用原始就绪方法的脚本之前完成。否则就是与 John/Kikito 相同的代码:

// Overrides jQuery-ready and makes it triggerable with $.triggerReady
// This script needs to be included before other scripts using the jQuery-ready.
// Tested with jQuery 1.7
(function(){
var readyList = [];

// Store a reference to the original ready method.
var originalReadyMethod = jQuery.fn.ready;

// Override jQuery.fn.ready
jQuery.fn.ready = function(){
if(arguments.length && arguments.length > 0 && typeof arguments[0] === 'function') {
  readyList.push(arguments[0]);
}

// Execute the original method.
originalReadyMethod.apply( this, arguments );
};

// Used to trigger all ready events
$.triggerReady = function() {
  $(readyList).each(function(){this();});
};
})();

I'm not sure whether it is advisable to override the ready method. Feel free to advise me on that. I have not yet found any side effects myself though.

我不确定是否建议覆盖 ready 方法。请随时给我建议。我自己还没有发现任何副作用。

回答by kikito

Just in case anyone needs it, I refined John's solution a bit so it could be used directly as an included javascript file.

以防万一有人需要它,我稍微改进了约翰的解决方案,以便它可以直接用作包含的 javascript 文件。

// jquery_trigger_ready.js
// this function is added to jQuery, it allows access to the readylist
// it works for jQuery 1.3.2, it might break on future versions
$.getReadyList = function() {
  if(this.readyList != null) { this.myreadylist = [].concat(this.readyList); }
  return this.myreadylist;
};

$(document).ready(function() {
  readylist = $.getReadyList();
});

$.triggerReady = function() {
  $(readylist).each(function(){this();});
}

Including this file after including jquery allows for triggering ready by invoking $.triggerReady(). Example:

在包含 jquery 之后包含此文件允许通过调用$.triggerReady(). 例子:

<html>
  <head>
    <title>trigger ready event</title>
    <script src="test2_files/jquery-1.js" type="text/javascript"></script>
    <script src="jquery_trigger_ready.js" type="text/javascript"></script>
  </head>
  <body>
    <input onclick="$.triggerReady();" value="trigger ready" type="button">
    <script type="text/javascript">
      $(document).ready(function(){
          alert("blah");
      });
    </script>
  </body>
</html>

By the way, I wanted to make it $(document).triggerReady(). If anyone is willing to share some advice on that, ill be appreciated.

顺便说一句,我想成功$(document).triggerReady()。如果有人愿意分享一些建议,不胜感激。

回答by Simone Gianni

We had the same problem and solved it another way.

我们遇到了同样的问题,并以另一种方式解决了它。

Instead of

代替

$(document).ready(function () {
  $('.specialClass').click(....

We used :

我们用了 :

$(document).bind('ready', function(event) {
  $('.specialClass', event.target).click(..

jQuery will trigger a "ready" event on the document as usual. When we load the content of a new div via ajax, we can write:

jQuery 会像往常一样在文档上触发“就绪”事件。当我们通过ajax加载一个新div的内容时,我们可以这样写:

loadedDiv.trigger('ready')

And have all the initialization performed only on the div, obtaining what expected.

并且只在 div 上执行所有初始化,获得预期的结果。

回答by Uoli

Simone Gianni's Answer I think is the most elegant and clean.

Simone Gianni 的答案我认为是最优雅和干净的。

and you can even simplify it to become even more easy to use:

您甚至可以简化它以使其更易于使用:

jQuery.fn.loadExtended = function(url,completeCallback){
    return this.load(url,function(responseText, textStatus, XMLHttpRequest) {
        if (completeCallback !== undefined && completeCallback !== null) {
            completeCallback(responseText, textStatus, XMLHttpRequest);
        }
        $(this).trigger("ready");
    });
};

So, now instead of using:

所以,现在而不是使用:

$(".container").load(url,function(responseText, textStatus, XMLHttpRequest) {
    $(this).trigger("ready");
});

you can just use:

你可以使用:

$(".container").loadExtended("tag_cloud.html");

or:

或者:

$(".container").loadExtended("tag_cloud.html",function(){ 
    alert('callback function') 
});

This has the advantage of only applying the trigger on the div that's being updated.

这具有仅在正在更新的 div 上应用触发器的优点。

回答by linkuha

If your new loaded HTML contain <script>elements and you try insert it into main HTML with pure JS (element.innerHTML = newHTML), then $(document).readyhandlers at newHTML and wrapped functions like (function() { /* some functions */ })();- will not execute because JQuery unbind 'ready'event after first triggering and you can not trigger it repeatly. PS. But you can use $.holdReady(true)and trigger when need.

如果您新加载的 HTML 包含<script>元素,并且您尝试使用纯 JS ( element.innerHTML = newHTML)将其插入到主 HTML 中,那么$(document).readynewHTML 处的处理程序和包装函数 ( function() { /* some functions */ })();- 将不会执行,因为 JQuery在第一次触发后取消绑定“就绪”事件并且您无法触发它重复。PS。但您可以$.holdReady(true)在需要时使用和触发。

So, try insert code with jquery method, $(element).html(newHTML). This solved similar problem for me, seems jquery handle js before inserting. Using this method you also will not see the <script>elements among DOM nodes (at browser's Elements Inspector for ex.)

因此,尝试使用 jquery 方法插入代码$(element).html(newHTML)。这为我解决了类似的问题,似乎 jquery 在插入之前处理了 js。使用此方法您也不会看到<script>DOM 节点之间的元素(例如在浏览器的 Elements Inspector 中)。