簡體   English   中英

通過動態插入的DOM元素進行AJAX調用,是否需要使用Mutation Observer?

[英]Make AJAX call via dynamically inserted DOM element, do I have to use a Mutation Observer?

在當前應用程序中,頁面上有一些元素以“空”開始,並通過AJAX調用加載其顯示數據。

一種簡單的實現方法是使用一個類(例如.ajax-loader )並遍歷每個類,然后從元素本身的data- attribute中加載AJAX數據。

所以像這樣( jsfiddle ):

<div class="ajax-loader" data-url="/echo/html/" data-html="<p>hello world</p>" data-delay="1">Loading...</div>

<script>
  $('.ajax-loader').each(function() {
    var ele = $(this);
    var url = ele.data('url');
    var html = ele.data('html');
    var delay = ele.data('delay');

    return $.post({
      url: url,
      data: {
        html: html,
        delay: delay
      }
    }).done(function(d) {
      ele.html(d);
    });
  });
</script>

現在,這可以正常工作,但是,當我需要將這些.ajax-loader元素動態插入頁面時,就會出現問題。 我的.each()函數僅運行一次,因此如果在頁面中插入了新的.ajax-loader元素,則不會再次運行(您可以通過單擊按鈕在上一個jsfiddle中看到它)。

因此,我放入了一個突變觀察器來檢測DOM的變化。 現在我的代碼如下所示( jsfiddle ):

<button class="insert-ele">Click to insert new AJAX object</button>
<div id="container">
  <div class="ajax-loader" data-url="/echo/html/" data-html="<p>Hello World!</p>" data-delay="1">Loading...</div>
</div>

<script>
$(document).ready(function() {
  // Insert new ".ajax-loader" objects on button click
  $('.insert-ele').on('click', function(e) {
    $('#container').append('<div class="ajax-loader" data-url="/echo/html/" data-html="<p>I was inserted via JS.</p>" data-delay="1">Loading...</div>');
    e.preventDefault();
  });

  // Define our ajaxLoader function
  var ajaxLoader = function() {
    var ele = $(this);
    ele.addClass('ajax-load-started');

    var url = ele.data('url');
    var html = ele.data('html');
    var delay = ele.data('delay');

    return $.post({
        url: url,
      data: {
        html: html,
        delay: delay
      }
    }).done(function(d) {
        ele.html(d);
      ele.addClass('ajax-load-completed');
      ele.removeClass('ajax-load-started');
    });
  };

  // Loop through each .ajax-loader, and load their AJAX request.
  $('.ajax-loader:not(.ajax-load-completed):not(.ajax-load-started)').each(ajaxLoader);

  // Observe DOM changes, and load AJAX data when it does change
  var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
  var observer = new MutationObserver(function(mutations) {
    $('.ajax-loader:not(.ajax-load-completed):not(.ajax-load-started)').each(ajaxLoader);
  });

  // Activate the observer
  var container = document.getElementById('container');
  observer.observe(container, {
    attributes: true, 
    childList: true, 
    subtree: true
  });
});
</script>

但是,查看突變觀察者瀏覽器兼容性 ,我發現它僅在IE 11中受支持。我需要支持IE 9,可能還需要IE 8,盡管那並不那么重要。

有沒有更好的方法可以做到這一點? 或者只是另一種方式可以使我更好地與瀏覽器兼容?

我也意識到我可以在$('.insert-ele').on('click')處理程序中運行$('.ajax-loader').each()函數,但是我想避免這種情況解決方案,如果可能的話。

突變觀察在這里並不適合(無論您如何實現):檢查DOM(或任何對象)的更改是很昂貴的,因為它需要保留對象的副本並遍歷整個對象事物,遞歸到對象的屬性以檢查差異。 就您而言,您無需知道任何更改,而是想知道何時發生了特定事件(將dom元素添加到頁面中)。

您想要一個“一刀切”的解決方案是正確的,並且實施起來應該不會太困難。 在某個地方,您有一個AJAX回調負責將這些元素添加到頁面中。 (如果對此負責的功能不止一個,那么現在是將它們整合為一個功能的時候了。)當此AJAX回調函數插入DOM元素時,讓它a)觸發您定義的回調,或b)觸發您的其他代碼可以監聽的自定義事件 (可能通過jQuery,但Backbone和其他庫也具有自定義事件實用程序)。 無論您采用哪種方法,都希望插入DOM元素的函數執行允許其他代碼響應該操作的操作。

如果負責將DOM元素插入頁面的代碼是第三方的,這可能會比較棘手。 (這是考慮是否最好編寫自己的實現的好時機。)查看該代碼的源代碼,並仔細檢查其是否不支持回調或事件或允許您與其集成的內容。 如果沒有,您仍然應該能夠通過偵聽load事件來響應DOM插入。

每個DOM元素加載到DOM中時都會觸發一個load事件。 您不能將事件偵聽器附加到正在插入的元素上,因為它們尚不存在,但是您可以使用事件委托 :在load事件的父元素上附加事件偵聽器,當元素具有已插入(因為事件從插入的元素到其父元素冒泡了)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM