昨天寫了一篇關於監視頁面動態產生元素問題的文章,引起了一些小小的爭議,不過我從中學到了很多。
文章在這,《jQuery下實現等待指定元素載入完畢》
當然 動態產生的節點元素 分很多種情況,這裡我們只分析ajax取得資料後產生元素問題。
昨天有大俠在下面評論,我學到了兩種方法,一是 ajaxSuccess 來監聽,二是 DOMNodeInserted 來監聽,
最終我選擇了 ajaxSuccess 而不打算用 DOMNodeInserted 。
不是因為 DOMNodeInserted 不好,這個方法還是相當不錯的,我以前都沒見過,(先學習了,留著以後備用)
只是因為 DOMNodeInserted 對每個節點產生都響應一次,所以會有上百次上千次的判斷,造成了不必要的浪費。
(PS:不知道我的理解是否正確,如果有不恰當的地方,還望各位大俠指出。)
所以我選擇了 ajaxSuccess ,但是還有個問題,ajaxSuccess 與 $.ajax() 內的 success 方法,
以及 jQuery 1.5 以後推薦的 done 方法,執行的先後順序是怎樣的呢?
我們先來做一個簡單的測試,代碼如下
1 (function(){ 2 var box = $("#ajaxtest .docs-room"); //測試資料顯示區元素 3 4 $("#btn-send").click(function(){ //綁定發送按鈕 5 box.html(""); //清空顯示區 6 7 $("<p>").html( (new Date).toLocaleString() ).appendTo(box); //添加測試事件 8 $.ajax({ 9 url: '/mvc/blog/news.aspx', //右側 暱稱,園齡 等資料頁面10 data: '{"blogApp":"' + currentBlogApp + '"}', //部落格blogApp11 type: 'post',12 dataType: 'text',13 contentType: 'application/json; charset=utf-8',14 //從 url 到 contentType 這幾行代碼是部落格園的,我直接拿過來用的。15 success: function(data) { //請求成功後調用16 $("<p>").html( "success [ " + $(data).eq(0).text() + " ]" ).appendTo(box);17 },18 complete: function(request) { //請求完成後調用19 $("<p>").html("complete [ " + $(request.responseText).eq(0).text() + " ]" ).appendTo(box);20 }21 }).done(function(data) { //請求成功後調用(deferred對象的方法)22 $("<p>").html("done success [ " + $(data).eq(0).text() + " ]" ).appendTo(box);23 }).always(function(data) { //請求完成後調用(deferred對象的方法)24 $("<p>").html("always complete [ " + $(data).eq(0).text() + " ]" ).appendTo(box);25 });26 });27 28 $("#btn-clear").click(function(){ //清除資料29 box.html("");30 });31 32 $(document).ajaxSuccess(function(evt, request){ //ajax監聽,所有ajax請求成功都執行33 $("<p>").html("ajaxSuccess [ " + $(request.responseText).eq(0).text() + " ]" ).appendTo(box);34 }).ajaxComplete(function(evt, request){ //ajax監聽,所有ajax請求完成都執行35 $("<p>").html("ajaxComplete [ " + $(request.responseText).eq(0).text() + " ]" ).appendTo(box);36 });37 38 }());
下面是測試區,大家可以點擊測試下。
測試控制區-測試資料顯示區
發現執行順序很有意思,always 竟然跑到 ajaxSuccess 前面去了。
與我原先預想的不太一樣,後來看了 deferred對象 方面的文章才弄懂,
這裡就不解釋了,大家自己去找這方面的資料吧,不過 done 和 always 要1.5以後的版本才能使用,這點要注意下。
我們可以肯定的是 ajaxSuccess 會在 success 和 done 之後執行,那麼可以肯定節點已經產生,
這時我們對這幾個節點進行補丁處理即可,下面是My Code,請各位大俠審查、
1 (function(){ //監聽ajax事件 2 $(document).ajaxSuccess(function(evt, request, settings, data) { 3 4 var patchs = { //頁面補丁方法集,把需要補丁的頁面名寫到這就可以了。 5 CommentForm: function(){ //評論頁面 6 $("#btn_comment_submit").removeClass("comment_btn").addClass("btn"); //提交按鈕 7 }, 8 sidecolumn: function(){//搜尋所在的頁面 9 $(".div_my_zzk").addClass("input-append"); //搜尋方塊10 $(".btn_my_zzk").removeClass("btn_my_zzk").addClass("btn"); //搜尋按鈕11 }12 }13 14 var _key = settings.url.split("/").pop().split(".").shift(); //取的ajax url的檔案名稱15 patchs[_key] && patchs[_key](); //如果有這個補丁,就應用補丁16 });17 })();
這樣既不會導致太多次的判斷,而且可以針對指定頁面的請求進行補丁處理。
這是目前我能想到最好的方法了,如果還有更完美的方法,還望大俠賜教。:-)