很多人喜歡Pjax 的魅力,我收集了一個博客的教程,將他們整合到一起。
這里只做備份用,很推薦去原文看看,尤其是評論區,說不定會有意想不到的收獲。
此系列文章更新于2015年2月
- 原文來源:INLOJV
第一部分
教程寫給自己的,所以日后可能有補充。首先這個pjax的代碼有好幾部分,來自網絡不同作者,經過本人封裝,教程就是按這幾個部分來進行的。這是第一部分,我把自己理解的大致原理說一下,pjax是 pushstate + ajax,分別百度可以得到相關資料,在此就不贅述了。
Ajax
ajax直白的理解就是請求一個鏈接所指向的頁面的其中一部分來替換當前頁面的一部分,比如我用的wordpress,典型的博客頁面,有頁面頭部、主體部分、側欄部分、頁面底部四個主要部分。
ajax請求的過程是如何的呢?比如我現在打開的是頁面A
,頁面A
中有一個a標簽,正常情況下點擊a標簽的鏈接會打開一個頁面B
,那么整個頁面A就會被替換成頁面B。然而,頁面A和頁面B有些結構是完全一樣的,比如頭部,底部,甚至是側欄,其實要替換的僅僅是主體部分而已,ajax就提供了這樣一個功能,它控制你在點擊a標簽的鏈接時,只抓取頁面B的主體部分來替換頁面A的主體部分,而頭部、底部、側欄不用替換(也就不用刷新)。
PushState
以上是最直白的理解,而pushstate則是干嘛的?HTML5里引用了新的API,history.pushState和history.replaceState,就是通過這個接口做到無刷新改變頁面URL的。因為用ajax替換局部頁面時,瀏覽器的地址是不會改變的,你替換為頁面B的主體,地址欄的url還是頁面A的,而且點擊瀏覽器的后退或前進按鈕地址欄url也是不會改變的,pushstate的作用則用來改變地址欄url的狀態。
那么PJAX就是以上兩者的結合。
開始我們必須對 被請求的頁面進行請求前的處理,這個處理非常重要,如果把被請求的頁面想象成一張圖片,那么這個處理就相當于對圖片進行剪裁,沒有處理之前,被請求的頁面B是完整的,請求過來就首先要預讀取一邊頁面B,而其實我們不必要將整個頁面都讀取,我們只需要讀取主體部分,所以我們可以把頭部、側欄和底部都先剪掉,只剩下主體部分,然后再請求過來替換頁面A中的主體部分。
這個剪裁的方法如下:
在對應的php頁面進行
<?php if( $_GET['ajx'] != 'container' ) { ?> //被剪裁掉的部分,比如: //<?php get_header(); ?> //<?php get_sidebar(); ?> //<?php get_footer(); ?> <?php } ?>
這個方法非常重要,包括評論分頁也需要這樣的處理,對pjax的速度是一大影響。了解了這個其實剩下的只需要把剩下的代碼超過去就可以了。當然,你不剪裁也是可以的,那也可以替換,但那就不算是真正的ajax了。目前大多數pjax的代碼都不會有這樣的處理。下面一篇是pjax的核心代碼以及一些說明。
第二部分
原文來源: http://www.inlojv.com/4967.html
處理過程
上篇我們提到了“剪裁”,本篇我們先來實際體驗一下被剪裁掉的頁面是如何的,這方便我們對接下來的頁面請求過程有一個感性的認識。
假設我的index.php首頁是這個結構:頭部、主題、側欄、底部 四大結構組成。
<?php get_header(); ?> <div id="container"> </div> <?php get_sidebar(); ?> <?php get_footer(); ?>
現在我先把頭部剪掉
<?php if( $_GET['ajx'] != 'container' ) { ?> <?php get_header(); ?> <?php } ?> <div id="container"> </div> <?php get_sidebar(); ?> <?php get_footer(); ?>
可以看到我用第一篇中所說的代碼將頭部包住了,這意味著我把頭部剪掉了。
原本首頁是?http://127.0.0.1/
?,現在我們以這樣的鏈接形式來訪問首頁?http://127.0.0.1/?ajx=container
打開這個鏈接你會發現,首頁的頭部不見了,由于頭部加載了css,你首頁的樣式也會消失,這個狀態就是我們想要ajax請求的,我們不需要頭部,把它給剪掉了,接著我們可以用同樣的方法剪掉側欄和底部,最后就會只剩下主體部分,如下:
<?php if( $_GET['ajx'] != 'container' ) { ?> <?php get_header(); ?> <?php } ?> <div id="container"> </div> <?php if( $_GET['ajx'] != 'container' ) { ?> <?php get_sidebar(); ?> <?php } ?> <?php if( $_GET['ajx'] != 'container' ) { ?> <?php get_footer(); ?> <?php } ?>
這就是真正需要ajax請求的頁面了。
我們需要把http://127.0.0.1/?ajx=container?
這樣的鏈接傳遞給ajax方法進行異步請求,
比如在頁面A?http://127.0.0.1/page-a
?中要請求頁面B,頁面A中的a標簽中指向頁面B的鏈接就應該是這樣的?http://127.0.0.1/page-b?ajx=container
?,
利用兩個js函數來對點擊的鏈接進行處理,加上后面的?=ajx=container
參數,在必要的時候后再去掉它們。
完整的PJAX代碼
var ajx_content = "#ajx_content"; function rerun() {} $(function() { rerun(); a(); }); function show_loading(e) { if ($("#loading_box").length == 0) { var div = "<div id='loading_box'></div><div id='loading'></div><div id='loading-text'></div></div>"; } if (e === true) { $("body").append(div); } else { $("#loading_box,#loading,#loading-text").fadeOut(400, function() { $(this).remove(); }); } } function body_am(id) { id = isNaN(id) ? $("#" + id).offset().top : id; $("body,html").animate({ scrollTop: id }, 600); return false; } function pluginRerun() { var plugin_scripts = $('script[src*="plugins"]'); plugin_scripts.each(function() { var url = $(this).attr("src"); $.getScript(url); }); } function addUrlPara(url, para) { var strArray = new Array(); strArray = url.split("?"); if (strArray.length == 1) { if (url.indexOf("#") != -1) { strArray = url.split("#"); return strArray[0] + "?" + para + "#" + strArray[1]; } return url + "?" + para; } else { if (url.indexOf(para) != -1) return url; return strArray[0] + "?" + para + "&" + strArray[1]; } } function removeUrlPara(url, para) { var strArray = new Array(); strArray = url.split(para); if (strArray.length == 1) { strArray = url.split("?" + para); return strArray[0]; } else { if (strArray[1].indexOf("&") != -1) { strArray = url.split(para + "&"); return strArray[0] + strArray[1]; } else { strArray = url.split("?" + para); return strArray[0] + strArray[1]; } } } function l() { history.replaceState({ url: window.document.location.href, title: window.document.title, html: $(document).find(ajx_content).html() }, window.document.title, document.location.href); } function a() { window.addEventListener("popstate", function(e) { if (e.state) { document.title = e.state.title; $(ajx_content).html(e.state.html); rerun(); } }); } function ajax(reqUrl, msg, data) { if (msg == "pagelink" || msg == "search") { show_loading(true); $(ajx_content).fadeTo("normal", 0); $("body,html").animate({ scrollTop: $("body").offset().top }, 810); var paraUrl = addUrlPara(reqUrl, "ajx=container"); } else if (msg == "comtpagenav") { to_anchor("#post-comment-list", 0); $("#comment_list").fadeTo(500, .2, function() { $("#comment_list").css("position", "relative"); }); reqUrl = removeUrlPara(reqUrl, "ajx=container"); paraUrl = addUrlPara(reqUrl, "ajx=comts"); } $.ajax({ url: paraUrl, data: data, beforeSend: function() { l(); }, success: function(data) { if (msg == "pagelink" || msg == "search") { $(ajx_content).replaceWith($(data).filter(ajx_content)); $(ajx_content).fadeTo(500, 1, function() { rerun(); }); show_loading(false); } else if (msg == "comtpagenav") { var content = $(data).find("#comment_list").html(); $("#comment_list").animate({ opacity: 0, top: 35 }, 200, function() { $("#comment_list").html(content); $("#comment_list").animate({ opacity: 1, top: 0 }, 400, function() { $("#comment_list").css("position", "inherit"); }); rerun(); }); } document.title = $(data).filter("title").text(); reqUrl = removeUrlPara(reqUrl, "ajx=comts"); var state = { url: reqUrl, title: $(data).filter("title").text(), html: $(data).filter(ajx_content).html() }; window.history.pushState(state, $(data).filter("title").text(), reqUrl); }, complete: function() {}, timeout: 5e3, error: function(request) { if (msg == msg == "pagelink" || msg == "search") { show_loading(false); location.href = reqUrl; } else if (msg == "comtpagenav") { $("#comment_list").fadeTo("normal", 1); $("#comt_svg").css("display", "none"); $("#comments_paginate").css("display", "block"); } else { location.href = reqUrl; } } }); } function check_x(url) { var url_string = new String(" , comment-page-, #respond, #comment, javascript:, oauth2, .jpg, .gif, .png"); var url_x = url_string.split(", "); for (var i in url_x) { if (url.indexOf(url_x[i]) >= 0) { return true; } } return false; } $("body").on("click", "a[target!=_blank]:not(.noajx)", function() { url = $(this).attr("href"); if (check_x(url) == true) return; ajax(url, "pagelink"); return false; }); $("body").on("submit", "#search .s-form", function() { ajax(this.action + '?=' + $(this).find("#s").val(), 'search', $(this).serialize()); return false; }); $("body").on("click", "#comments_paginate a", function() { ajax($(this).attr("href"), "comtpagenav"); return false; });
核心就是ajax(reqUrl, msg, data)函數了,還有兩個函數需要說明一下
1、check_x(url)函數 —— 這是檢查a標簽的鏈接中是否有需要排除的字符,有時候某些a標簽是不需要ajax請求的,比如/wp-login.php,圖片鏈接帶有.jpg、.gif、.png 等等,都不需要ajax請求,我們得把它們排除掉,加入到check_x(url)內的排除列表內。
2、rerun()函數 —— 這個函數方便我們對其他js腳本進行重新加載,相當于一個回調函數,比如有的站用了多說評論系統,ajax請求時是不會請求css和js的,只抓取html結構,所以ajax加載后多說需要的js就不會一起加過來,這時候就需要把多說的js放進rerun()函數進行重新加載。
好了,PJAX教程就介紹到這里,適合有一定js基礎的朋友看,如果連js都不懂,那只能靠百度了。
第三部分
原文來源: http://www.inlojv.com/5011.html
全站pjax教程一和二已經將重點與核心代碼呈現過了,還有一些執行上的問題在此補充一下
1、并不是所有的pjax代碼都相同?
網上有很多所謂的全站ajax代碼,其實僅僅是頁面ajax,全站還要兼顧很多東西,搜索、評論、重載回調等等,另外有一些pushstate的使用也不相同,有的pjax后退是沒有緩存的,這樣這些代碼的前進和后退,就會重新請求一次push進去的歷史鏈接,所以你會發現有的后退是重新執行一遍代碼會有loading效果,而有的不是,是很干脆地切換回去。教程[二]提供的代碼屬于后者。
2、ajax替換頁面容器所用的函數不同
比如教程[二]中ajax執行成功后有這么一句$(ajx_content).replaceWith($(data).filter(ajx_content));
,有一些代碼則不同,有可能是這樣的:$(ajx_content).html($(data).filter(ajx_content).html());
,還有的用的不是filter()
而是find()
?。這兩個函數是有區別的,一個是針對同級元素,一個是針對子元素;當對請求頁面進行剪裁時,容器可能暴露在最外面,此時就需要用filter;當沒有剪裁時就只能用find。
3、“剪裁”的方式
有的小伙伴可能對“剪裁”并不熟悉,只是生搬硬套,這也導致了后面需要做很多工作,比如:ajax請求后瀏覽器的頁面標題需要通過修改頁面結構來組合獲取。其實剪裁的時候保留title標簽,title就可以直接用document.title = $(data).filter("title").text();
來獲取了。
4、重載回調
這個算是個很大的難題,因為解決這樣的問題其實相當于把jquery的基礎給學了一遍,我不是專業的,現在也還不是很明白這些代碼的執行到底應該怎么描述。ajax請求不會請求到容器之外的腳本文件,除非你把js寫在容器之內,比如之前我試過把百度分享代碼寫在footer.php
,但ajax始終不加載,只能把它寫在single.php
的容器里面。 還有很多插件會加載額外的js腳本,比如多說評論、某蝦米音樂插件、圖片燈箱、代碼高亮 等等,它們在ajax請求過來后都會失效,這時候就需要為ajax提供一個回調函數,方便在ajax過程執行完畢之后重新加載這些模塊的js腳本。
有的插件提供了執行函數,比如slimbox燈箱,會有一個slimbox()
函數;Google prettify語法高亮,會有一個prettify()
函數,這些都可以在ajax回調時放進去重新加載,使得加載后這些功能不失效。
有的插件則不會提供這種函數,比如多說,它只有一整個js腳本,加載方式可以看這里兩種方式執行外部插件掛載的js腳本
下面我就以最典型的Willin Kan版的ajax評論來舉個例子,因為很多小伙伴完成頁面ajax之后,評論ajax總是失效,下面先看看這個評論ajax代碼:
var theme_dir = $('head #default-css').attr('href').split('style.css')[0]; // 主題路徑 ,以style.css分割href,第一段就是主題路徑 /** * WordPress jQuery-Ajax-Comments v1.3 by Willin Kan. * URI: http://kan.willin.org/?p=1271 */ ??? var commentform = '#comment_form', // ××× form表單id ??? comment = 'c_tarea', // ××× textarea 的id 不帶# ??? commentlist = 'comment-list',? // ××× 評論列表ul或ol的class,不帶點 ??? respond = '#respond',? // ××× 評論插入位置,插入在這個id之前 ??? homeUrl = document.location.href.match(/http:\/\/([^\/]+)\//i)[0], // 主頁地址,用于下面的提交函數 ??? txt1 = '<div id="loading" class="text-info"> 正在提交, 請稍候...</div>', ??? txt2 = '<div id="error">#</div>', ??? txt3 = '"><div class="text-success"> OK !', ??? edt1 = ' 刷新頁面之前您可以<a rel="nofollow" class="comment-reply-link" href="#edit" onclick=\'return addComment.moveForm("', ??? edt2 = ')\'>再次編輯評論</a></div>', ??? cancel_edit = '取消編輯', ??? edit, ??? num = 1, ??? $comments = $('#response'), // 評論數 ??? $cancel = $('#cancel-comment-reply-link'), ??? cancel_text = $cancel.text(), ??? $submit = $(commentform+ '#submit'); ??? $submit.attr('disabled', false), ??? $body = (window.opera) ? (document.compatMode == "CSS1Compat" ? $('html') : $('body')) : $('html,body'), ??? comm_array = []; ??? comm_array.push(''); ??? $('#'+comment).after(txt1 + txt2); // ××× textarea的id或class ??? $('#loading').hide(); ??? $('#error').hide(); ??? // 評論提交 // $(commentform).submit(? // 非動態綁定 $(document).on("submit", commentform, //動態綁定 ??? function() { ??????? if (edit) $('#'+comment).after('<input type="text" name="edit_id" id="edit_id" value="' + edit + '" style="display:none;" />'); ??????? $submit.attr('disabled', true).fadeTo('slow', 0.5); ??????? $('#loading').slideDown(); ??????? $.ajax({ ??????????? url: theme_dir + '/comt-ajax.php', ??????????? data: $(this).serialize() , ??????????? type: $(this).attr('method'), ??????????? error: function(request) { ??????????????? $('#loading').slideUp(); ??????????????? $("#error").slideDown().html(request.responseText); ??????????????? setTimeout(function() { ??????????????????? $submit.attr('disabled', false).fadeTo('slow', 1); ??????????????????? $('#error').slideUp(); ??????????????? }, ??????????????? 3000); ??????????? }, ??????????? success: function(data) { ??????????????? $('#loading').hide(); ??????????????? comm_array.push($('#'+comment).val()); ??????????????? $('textarea').each(function() { ??????????????????? this.value = '' ??????????????? }); ??????????????? var t = addComment, ??????????????? cancel = t.I('cancel-comment-reply-link'), ??????????????? temp = t.I('wp-temp-form-div'), ??????????????? respond = t.I(t.respondId), ??????????????? post = t.I('comment_post_ID').value, ??????????????? parent = t.I('comment_parent').value; ?? ??? ??? ??? ?// 增加評論數 ??????????????? if (!edit && $comments.length) { ??????????????????? n = parseInt($comments.text().match(/\d+/)); // 匹配數字 ??????????????????? $comments.text($comments.text().replace(n, n + 1)); ??????????????? } ?? ??? ??? ??? ?// 評論顯示 ??????????????? new_htm = '" id="new_comm_' + num + '"></'; ??????????????? new_htm = (parent == '0') ? ('\n<ol style="clear:both;" class="'+commentlist+'" ' +? new_htm + 'ol>') : ('\n<ul class="children' + new_htm + 'ul>'); ??????????????? ok_htm = '\n<div class="ajax-notice" id="success_' + num + txt3; ??????????????? div_ = (document.body.innerHTML.indexOf('div-comment-') == -1) ? '': ((document.body.innerHTML.indexOf('li-comment-') == -1) ? 'div-': ''); ??????????????? ok_htm = ok_htm.concat(edt1, div_, 'comment-', parent, '", "', parent, '", "respond", "', post, '", ', num, edt2); ??????????????? ok_htm += '</span><span></span>\n'; ??????????????? ok_htm += '</div>\n'; ?? ??? ??? ??? ?if($('#comments .comment-list').length>0){ // ××××××××××××××××××××非嵌套評論時,新評論顯示插入的位置(按自己的喜好修改顯示位置) ?? ??? ??? ??? ??? ?$('#comments .comment-list').before(new_htm); ?? ??? ??? ??? ?} else{ ?? ??? ??? ??? ??? ?$('#respond').after(new_htm); ?? ??? ??? ??? ?} ??????????????? $('#new_comm_' + num).append(data); ??????????????? $('#new_comm_' + num + ' li').append(ok_htm); ??????????????? $body.animate({scrollTop: $('#new_comm_' + num).offset().top - 200},900); ??????????????? countdown(); ??????????????? num++; ??????????????? edit = ''; ??????????????? $('*').remove('#edit_id'); ??????????????? cancel.style.display = 'none'; ??????????????? cancel.onclick = null; ??????????????? t.I('comment_parent').value = '0'; ??????????????? if (temp && respond) { ??????????????????? temp.parentNode.insertBefore(respond, temp); ??????????????????? temp.parentNode.removeChild(temp) ??????????????? } ??????????? } ??????? }); ??????? return false; ??? }); ??? addComment = { ??????? moveForm: function(commId, parentId, respondId, postId, num) { ??????????? var t = this, ??????????? div, ??????????? comm = t.I(commId), ??????????? respond = t.I(respondId), ??????????? cancel = t.I('cancel-comment-reply-link'), ??????????? parent = t.I('comment_parent'), ??????????? post = t.I('comment_post_ID'); ??????????? if (edit) exit_prev_edit(); ??????????? num ? (t.I(comment).value = comm_array[num], edit = t.I('new_comm_' + num).innerHTML.match(/(comment-)(\d+)/)[2], $new_sucs = $('#success_' + num), $new_sucs.hide(), $new_comm = $('#new_comm_' + num), $new_comm.hide(), $cancel.text(cancel_edit)) : $cancel.text(cancel_text); ??????????? t.respondId = respondId; ??????????? postId = postId || false; ??????????? if (!t.I('wp-temp-form-div')) { ??????????????? div = document.createElement('div'); ??????????????? div.id = 'wp-temp-form-div'; ??????????????? div.style.display = 'none'; ??????????????? respond.parentNode.insertBefore(div, respond) ??????????? } ! comm ? (temp = t.I('wp-temp-form-div'), t.I('comment_parent').value = '0', temp.parentNode.insertBefore(respond, temp), temp.parentNode.removeChild(temp)) : comm.parentNode.insertBefore(respond, comm.nextSibling); ??????????? $body.animate({scrollTop: $('#respond').offset().top - 180},400); ??????????? if (post && postId) post.value = postId; ??????????? parent.value = parentId; ??????????? cancel.style.display = ''; ??????????? cancel.onclick = function() { ??????????????? if (edit) exit_prev_edit(); ??????????????? var t = addComment, ??????????????? temp = t.I('wp-temp-form-div'), ??????????????? respond = t.I(t.respondId); ??????????????? t.I('comment_parent').value = '0'; ??????????????? if (temp && respond) { ??????????????????? temp.parentNode.insertBefore(respond, temp); ??????????????????? temp.parentNode.removeChild(temp); ??????????????? } ??????????????? this.style.display = 'none'; ??????????????? this.onclick = null; ??????????????? return false; ??????????? }; ??????????? try { ??????????????? t.I(comment).focus(); ??????????? } ???????????? catch(e) {} ??????????? return false; ??????? }, ??????? I: function(e) { ??????????? return document.getElementById(e); ??????? } ??? }; ??? function exit_prev_edit() { ??????? $new_comm.show(); ??????? $new_sucs.show(); ??????? $('textarea').each(function() { ??????????? this.value = '' ??????? }); ??????? edit = ''; ??? } ??? var wait = 15, ??? submit_val = $submit.val(); ??? function countdown() { ??????? if (wait > 0) { ??????????? $submit.val(wait); ??????????? wait--; ??????????? setTimeout(countdown, 1000); ??????? } else { ??????????? $submit.val(submit_val).attr('disabled', false).fadeTo('slow', 1); ??????????? wait = 15; ??????? } ??? } ??? function grin(a) { ??????? var b; ??????? a = " " + a + " "; ??????? if (document.getElementById(comment) && document.getElementById(comment).type == "textarea") { ??????????? b = document.getElementById(comment) ??????? } else { ??????????? return false ??????? } ??????? if (document.selection) { ??????????? b.focus(); ??????????? sel = document.selection.createRange(); ??????????? sel.text = a; ??????????? b.focus() ??????? } else if (b.selectionStart || b.selectionStart == "0") { ??????????? var c = b.selectionStart; ??????????? var d = b.selectionEnd; ??????????? var e = d; ??????????? b.value = b.value.substring(0, c) + a + b.value.substring(d, b.value.length); ??????????? e += a.length; ??????????? b.focus(); ??????????? b.selectionStart = e; ??????????? b.selectionEnd = e ??????? } else { ??????????? b.value += a; ??????????? b.focus() ??????? } ??? }
上面的代碼有些選擇器是針對我自己的主題的,所以僅供參考,這個不重要。重點是當各種變量賦值完畢后,那一句$(document).on("submit", commentform,?
,這個是關鍵,意思是這個on方法把submit事件冒泡綁定到了document上,這個時候submit事件里面的所有動作就不會受到頁面ajax加載的影響。你可以注意到上面有一句$('#'+comment).after(txt1 + txt2);
?這個是在提交評論時顯示的loading提示文字,它沒有被包含在submit事件里面,所以它是受到頁面ajax加載影響的!也就是說:頁面ajax加載后,你點擊評論提交按鈕,此時不會顯示loading提示文字,但卻能進行ajax評論提交。如果你把這段提示放進submit里面去,那么整個評論ajax就和頁面ajax完全相互獨立了,它們可以互不影響,完全兼容。
另外,你可能注意到在$(document).on("submit", commentform,?
上一句注釋是這樣的$(commentform).submit(
,這表示你沒有用on方法將submit冒泡到document之上,此時這就和上面那個loading提示文字是一樣的,整個評論ajax就會受到頁面ajax的影響。那么如果不用on方法,應該怎么兼容?看下面的代碼:
var theme_dir = $('head #default-css').attr('href').split('style.css')[0]; // 主題路徑 ,以style.css分割href,第一段就是主題路徑 /** ?* WordPress jQuery-Ajax-Comments v1.3 by Willin Kan. ?* URI: http://kan.willin.org/?p=1271 ?*/ $(document).ready(function() { ??? ajaxComt(); }); function ajaxComt(){ ??? var commentform = '#comment_form', // ××× form表單id ??? comment = 'c_tarea', // ××× textarea 的id 不帶# ??? commentlist = 'comment-list',? // ××× 評論列表ul或ol的class,不帶點 ??? respond = '#respond',? // ××× 評論插入位置,插入在這個id之前 ??? homeUrl = document.location.href.match(/http:\/\/([^\/]+)\//i)[0], // 主頁地址,用于下面的提交函數 ??? txt1 = '<div id="loading" class="text-info"> 正在提交, 請稍候...</div>', ??? txt2 = '<div id="error">#</div>', ??? txt3 = '"><div class="text-success"> OK !', ??? edt1 = ' 刷新頁面之前您可以<a rel="nofollow" class="comment-reply-link" href="#edit" onclick=\'return addComment.moveForm("', ??? edt2 = ')\'>再次編輯評論</a></div>', ??? cancel_edit = '取消編輯', ??? edit, ??? num = 1, ??? $comments = $('#response'), // 評論數 ??? $cancel = $('#cancel-comment-reply-link'), ??? cancel_text = $cancel.text(), ??? $submit = $(commentform+ '#submit'); ??? $submit.attr('disabled', false), ??? $body = (window.opera) ? (document.compatMode == "CSS1Compat" ? $('html') : $('body')) : $('html,body'), ??? comm_array = []; ??? comm_array.push(''); ??? $('#'+comment).after(txt1 + txt2); // ××× textarea的id或class ??? $('#loading').hide(); ??? $('#error').hide(); ??? // 評論提交 $(commentform).submit(? // 非動態綁定 // $(document).on("submit", commentform, // 動態綁定 ??? function() { ??????? if (edit) $('#'+comment).after('<input type="text" name="edit_id" id="edit_id" value="' + edit + '" style="display:none;" />'); ??????? $submit.attr('disabled', true).fadeTo('slow', 0.5); ??????? $('#loading').slideDown(); ??????? $.ajax({ ??????????? url: theme_dir + '/comt-ajax.php', ??????????? data: $(this).serialize() , ??????????? type: $(this).attr('method'), ??????????? error: function(request) { ??????????????? $('#loading').slideUp(); ??????????????? $("#error").slideDown().html(request.responseText); ??????????????? setTimeout(function() { ??????????????????? $submit.attr('disabled', false).fadeTo('slow', 1); ??????????????????? $('#error').slideUp(); ??????????????? }, ??????????????? 3000); ??????????? }, ??????????? success: function(data) { ??????????????? $('#loading').hide(); ??????????????? comm_array.push($('#'+comment).val()); ??????????????? $('textarea').each(function() { ??????????????????? this.value = '' ??????????????? }); ??????????????? var t = addComment, ??????????????? cancel = t.I('cancel-comment-reply-link'), ??????????????? temp = t.I('wp-temp-form-div'), ??????????????? respond = t.I(t.respondId), ??????????????? post = t.I('comment_post_ID').value, ??????????????? parent = t.I('comment_parent').value; ?? ??? ??? ??? ?// 增加評論數 ??????????????? if (!edit && $comments.length) { ??????????????????? n = parseInt($comments.text().match(/\d+/)); // 匹配數字 ??????????????????? $comments.text($comments.text().replace(n, n + 1)); ??????????????? } ?? ??? ??? ??? ?// 評論顯示 ??????????????? new_htm = '" id="new_comm_' + num + '"></'; ??????????????? new_htm = (parent == '0') ? ('\n<ol style="clear:both;" class="'+commentlist+'" ' +? new_htm + 'ol>') : ('\n<ul class="children' + new_htm + 'ul>'); ??????????????? ok_htm = '\n<div class="ajax-notice" id="success_' + num + txt3; ??????????????? div_ = (document.body.innerHTML.indexOf('div-comment-') == -1) ? '': ((document.body.innerHTML.indexOf('li-comment-') == -1) ? 'div-': ''); ??????????????? ok_htm = ok_htm.concat(edt1, div_, 'comment-', parent, '", "', parent, '", "respond", "', post, '", ', num, edt2); ??????????????? ok_htm += '</span><span></span>\n'; ??????????????? ok_htm += '</div>\n'; ?? ??? ??? ??? ?if($('#comments .comment-list').length>0){ // ××××××××××××××××××××非嵌套評論時,新評論顯示插入的位置(按自己的喜好修改顯示位置) ?? ??? ??? ??? ??? ?$('#comments .comment-list').before(new_htm); ?? ??? ??? ??? ?} else{ ?? ??? ??? ??? ??? ?$('#respond').after(new_htm); ?? ??? ??? ??? ?} ??????????????? $('#new_comm_' + num).append(data); ??????????????? $('#new_comm_' + num + ' li').append(ok_htm); ??????????????? $body.animate({scrollTop: $('#new_comm_' + num).offset().top - 200},900); ??????????????? countdown(); ??????????????? num++; ??????????????? edit = ''; ??????????????? $('*').remove('#edit_id'); ??????????????? cancel.style.display = 'none'; ??????????????? cancel.onclick = null; ??????????????? t.I('comment_parent').value = '0'; ??????????????? if (temp && respond) { ??????????????????? temp.parentNode.insertBefore(respond, temp); ??????????????????? temp.parentNode.removeChild(temp) ??????????????? } ??????????? } ??????? }); ??????? return false; ??? }); ??? addComment = { ??????? moveForm: function(commId, parentId, respondId, postId, num) { ??????????? var t = this, ??????????? div, ??????????? comm = t.I(commId), ??????????? respond = t.I(respondId), ??????????? cancel = t.I('cancel-comment-reply-link'), ??????????? parent = t.I('comment_parent'), ??????????? post = t.I('comment_post_ID'); ??????????? if (edit) exit_prev_edit(); ??????????? num ? (t.I(comment).value = comm_array[num], edit = t.I('new_comm_' + num).innerHTML.match(/(comment-)(\d+)/)[2], $new_sucs = $('#success_' + num), $new_sucs.hide(), $new_comm = $('#new_comm_' + num), $new_comm.hide(), $cancel.text(cancel_edit)) : $cancel.text(cancel_text); ??????????? t.respondId = respondId; ??????????? postId = postId || false; ??????????? if (!t.I('wp-temp-form-div')) { ??????????????? div = document.createElement('div'); ??????????????? div.id = 'wp-temp-form-div'; ??????????????? div.style.display = 'none'; ??????????????? respond.parentNode.insertBefore(div, respond) ??????????? } ! comm ? (temp = t.I('wp-temp-form-div'), t.I('comment_parent').value = '0', temp.parentNode.insertBefore(respond, temp), temp.parentNode.removeChild(temp)) : comm.parentNode.insertBefore(respond, comm.nextSibling); ??????????? $body.animate({scrollTop: $('#respond').offset().top - 180},400); ??????????? if (post && postId) post.value = postId; ??????????? parent.value = parentId; ??????????? cancel.style.display = ''; ??????????? cancel.onclick = function() { ??????????????? if (edit) exit_prev_edit(); ??????????????? var t = addComment, ??????????????? temp = t.I('wp-temp-form-div'), ??????????????? respond = t.I(t.respondId); ??????????????? t.I('comment_parent').value = '0'; ??????????????? if (temp && respond) { ??????????????????? temp.parentNode.insertBefore(respond, temp); ??????????????????? temp.parentNode.removeChild(temp); ??????????????? } ??????????????? this.style.display = 'none'; ??????????????? this.onclick = null; ??????????????? return false; ??????????? }; ??????????? try { ??????????????? t.I(comment).focus(); ??????????? } ???????????? catch(e) {} ??????????? return false; ??????? }, ??????? I: function(e) { ??????????? return document.getElementById(e); ??????? } ??? }; ??? function exit_prev_edit() { ??????? $new_comm.show(); ??????? $new_sucs.show(); ??????? $('textarea').each(function() { ??????????? this.value = '' ??????? }); ??????? edit = ''; ??? } ??? var wait = 15, ??? submit_val = $submit.val(); ??? function countdown() { ??????? if (wait > 0) { ??????????? $submit.val(wait); ??????????? wait--; ??????????? setTimeout(countdown, 1000); ??????? } else { ??????????? $submit.val(submit_val).attr('disabled', false).fadeTo('slow', 1); ??????????? wait = 15; ??????? } ??? } ??? function grin(a) { ??????? var b; ??????? a = " " + a + " "; ??????? if (document.getElementById(comment) && document.getElementById(comment).type == "textarea") { ??????????? b = document.getElementById(comment) ??????? } else { ??????????? return false ??????? } ??????? if (document.selection) { ??????????? b.focus(); ??????????? sel = document.selection.createRange(); ??????????? sel.text = a; ??????????? b.focus() ??????? } else if (b.selectionStart || b.selectionStart == "0") { ??????????? var c = b.selectionStart; ??????????? var d = b.selectionEnd; ??????????? var e = d; ??????????? b.value = b.value.substring(0, c) + a + b.value.substring(d, b.value.length); ??????????? e += a.length; ??????????? b.focus(); ??????????? b.selectionStart = e; ??????????? b.selectionEnd = e ??????? } else { ??????????? b.value += a; ??????????? b.focus() ??????? } ??? } } // end Ajax評論
代碼的核心內容和前面是一樣的,只不過我將整段評論代碼寫成了一個ajaxComt()
函數,也就是將代碼用function ajaxComt(){...}
包住,可以看到,此時submit事件并非動態綁定,只要這樣
$(document).ready(function() { ??? ajaxComt(); });
就和原來不用函數包住的時候沒什么區別了。那么這個ajaxComt()
函數,就是我們放在頁面ajax回調里面重新加載的東西。ajax方法里面會有幾個執行先后的參數,beforeSend、success、complete ,我們可以把它放在complete里面:
complete: function() { // 頁面ajax完成后加載 ?? ?ajaxComt(); }
這樣就和動態綁定沒什么區別了。說法的區別從我個人角度來看就是:前者屬于冒泡綁定,頁面ajax和評論ajax是互不影響的;后者屬于先后執行,頁面ajax先執行完畢再執行一遍評論ajax 。
第四部分
原文來源: http://www.inlojv.com/5026.html
教程進行到第四已然顯得有些羅嗦了,本篇主要是本人記錄自己遇到的一些細節問題和網上的各種pjax代碼版本,權當補充篇來看吧。
搜索ajax表單序列化
最近想把主題換成經典的twentytwelve
,也試著把它pjax化,其中遇到一個搜索ajax的問題,按理說其他主題能實現,沒問題,這個也應該可以,但我把代碼搬上去之后,發現搜索ajax返回沒有返回正確的頁面,這里首先要說的就是WordPress正常情況下的搜索請求鏈接應該是這樣的http://127.0.0.1/?=xxx
,xxx表示你搜索的關鍵字,而由于有后端的處理(也就是教程[一]中的“剪裁”),發送給ajax的請求鏈接一般是類似?ajx=container
這樣的后綴(其他版本有可能是這樣?action=pjax
),那么搜索ajax的請求鏈接能不能這樣http://127.0.0.1/?=xxx?ajx=container
?答案是不能。只能把?號換成&號,變成這樣http://127.0.0.1/?=xxx&ajx=container
,所以在搜索ajax的請求鏈接上要加一些判斷,如果是搜索,那么得改一改鏈接附加的參數形式。
以上只是一個細節,我在修改twentytwelve時沒有返回應有的頁面,把搜索鏈接http://127.0.0.1/?=xxx&ajx=container
直接輸入到瀏覽器打開,發現也不是搜索結果頁面,找了半天才發現是form表單序列化的問題,$.ajax()
方法有幾個參數,其中我們要把序列化的表單信息放入到ajax方法的data參數內。賦值?data = $('#searchform').serialize();
?。其中#searchform是form表單的id

以上只是一個例子,條件判斷可以按自己的思路來做改變。如此一來,搜索ajax就沒有問題了。