【问题标题】:Does AJAX loaded content get a "document.ready"?AJAX 加载的内容是否获得“document.ready”?
【发布时间】:2020-01-30 02:20:20
【问题描述】:

昨天我遇到了一个问题,我分配的 .on('click') 事件处理程序无法正常工作。原来这是因为我试图在该元素存在于 DOM 之前应用那个 .on('click'),因为它是通过 AJAX 加载的,因此当 document.ready() 到达那个点时它还不存在。

我用一个尴尬的解决方法解决了这个问题,但我的问题是,如果我要在 ajax 加载的内容中放置一个 <script> 标记并在其中放置另一个 document.ready(),那么第二个 document.ready() 是否只会被解析一次ajax 内容加载完成了吗?换句话说,它是否认为单独加载的 ajax 内容是另一个 document,如果是这样,那么在该 ajax 加载的 HTML 中还有另一个 document.ready() 是否像我认为的那样工作?

或者;处理这种情况的更好方法是什么? (需要将事件监听器附加到 document.ready() 上尚不存在的 DOM 元素)

【问题讨论】:

  • 对于事件处理程序,使用事件委托。对于其他任何事情(例如插件初始化),请使用 AJAX 调用的回调函数。

标签: jquery event-handling addeventlistener document-ready


【解决方案1】:

回答您的问题:不,一旦 ajax 请求完成,document.ready 将不会再次触发。 (ajax 中的内容已加载到您的文档中,因此 ajax 内容没有第二个文档)。

要解决您的问题,只需将事件侦听器添加到您将 ajax 内容加载到其中的元素中。 例如:

$( "div.ajaxcontent-container" ).on( "click", "#id-of-the-element-in-the-ajax-content", function() {
  console.log($( this ));
});

对于#id-of-the-element-in-the-ajax-content,您可以使用在$("selector") 中使用的任何选择器。唯一不同的是,只会选择div.ajaxcontent-container 下的元素。

工作原理: 只要div.ajaxcontent-container 存在,所有匹配选择器#id-of-the-element-in-the-ajax-content 的元素(如果它们现在存在或仅在将来存在)都会触发此点击事件。

【讨论】:

  • 谢谢!大多数答案都是相同的,但您的答案专门回答了我的问题,然后继续解释事件委托。干杯!
  • 实际上 document.ready 将在 ajax 加载的 HTML 中调用。尝试添加到 ajax 加载页面 你会看到该消息被记录下来。但是在ajax之后不会触发主页上的function.ready ..只是为了清楚。
  • @VitaliyMarkitanov 你能解释一下这个 function.ready 在主页上没有在 ajax 之后触发
  • 看看这个伪页面 $(readyParentWhenParenLoaded) $(readyChild) 所以当你通过ajax调用从父页面加载子页面时,readyParentWhenParenLoaded 将不会被调用,但 readyChild 会
  • 很好的答案,节省了我的时间,因为当时我不了解事件转储和冒泡。这种方法的关键特性是将事件处理程序添加到 DOM 的动态加载部分的不可移动父级。
【解决方案2】:

由于安全原因,生成的 ajax 调用中的 Javascript 将不会被执行(默认情况下)。此外,您不能直接将事件绑定到不存在的元素。
可以将事件绑定到某个确实存在的父级,并告诉它检查它的子级:

$(document).ready(function(){
    $(document).on('eventName', '#nonExistingElement', function(){ alert(1); }
    // or:
    $('#existingParent').on('eventName', '#nonExistingElement', function(){ alert(1); }
});

始终尽量靠近触发元素,这将防止不必要的 DOM 冒泡


如果你有一些奇怪的功能,你可以这样做:

function bindAllDocReadyThings(){
    $('#nonExistingElement').off().on('eventName', function(){ alert(1); }
    // Note the .off() this time, it removes all other events to set them again
}
$(document).ready(function(){
    bindAllDocReadyThings();
});
$.ajaxComplete(function(){
    bindAllDocReadyThings();
});

【讨论】:

  • 如果您在所有加载的页面上都没有这些功能,这将无法正常工作。因此,我建议添加类似$(document).ajaxStart(function() { delete window.bindAllDocReadyThings; }); 的内容,而是将文档中的函数定义为bindAllDocReadyThings = function () { ... }
【解决方案3】:

试试这个,这不起作用,因为您的控件尚未创建并且您正在尝试附加事件,如果您在事件上使用它会正常工作。如果您遇到任何问题,请告诉我。

$(document).ready(function(){
    $(document).on('click', '#element', function (evt) {
        alert($(this).val());
    });
});

【讨论】:

    【解决方案4】:

    这里的答案是委托事件:

    JSFiddle

    JSFiddle - Truly dynamic

    jQuery

    $(document).ready(function(){
        // Listen for a button within .container to get clicked because .container is not dynamic
        $('.container').on('click', 'input[type="button"]', function(){
            alert($(this).val());
        });
    
        // we bound the click listener to .container child elements so any buttons inside of it get noticed
        $('.container').append('<input type="button" class="dynamically_added" value="button2">');
        $('.container').append('<input type="button" class="dynamically_added" value="button3">');
        $('.container').append('<input type="button" class="dynamically_added" value="button4">');
        $('.container').append('<input type="button" class="dynamically_added" value="button5">');
    });
    

    HTML

    <div class="container">
        <input type="button" class="dynamically_added" value="button1">
    </div>
    

    【讨论】:

      【解决方案5】:

      我正在和一个有类似要求的朋友一起开发代码库。如果您只想附加事件处理程序,委托事件处理程序选项绝对是最好的。另一种方法,尤其是如果您需要在 $(document).ready 函数中进行其他 DOM 处理时,是将要运行的代码放入代码末尾的脚本元素中。基本上,而不是:

      <script type="text/javascript">
        $(document).ready(function() {
          // Your code here
        });
      </script>
      <!-- rest of dynamically loaded HTML -->
      

      尝试交换脚本和 HTML 的其余部分,这样你就有了:

      <!-- rest of dynamically loaded HTML -->
      <script type="text/javascript">
        // Your code here
      </script>
      

      这会强制浏览器仅在加载了动态加载的 HTML 中的所有其他 DOM 元素后才处理您的代码。当然,这意味着您必须通过使用 CSS/HTML 而不是 JS 来确保插入的 HTML 不会产生意外的 UI 后果。它是多年前的一个古老的 Javascript 技巧。作为奖励,您不再需要 jQuery。

      我应该提到,在 Chromium v​​34 中,将第二个 $(document).ready 调用放在动态加载的 HTML 中的 &lt;script&gt; 标记内似乎等待动态加载的 DOM 加载,然后按照您的描述运行函数。我不确定这种行为是否标准,因为它在尝试使用其中的此类代码进行自动化测试时让我非常难过。

      【讨论】:

        【解决方案6】:

        JQuery AJAX .load() 具有处理此问题的内置功能。 而不是简单的$('div#content').load('such_a_such.url');,您应该包含一个回调函数。 JQuery .load() 为以下内容提供了空间:

        $('div#content').load('such_a_such.url',
            { data1: "First Data Parameter",
              data2: 2,
              data3: "etc" },
            function(){ $('#span1').text("This function is the equivalent of");
                        $('#span2').text("the $(document).ready function.");
            }
         );
        

        但是,您不需要包含 data 参数。

        $( "#result" ).load( "ajax/test.html", function() { alert("加载完成"); });

        http://api.jquery.com/load/

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-11-12
          相关资源
          最近更新 更多