全站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 。
好了,教程[三]就到此结束。
本站文章除注明转载/出处外,均为本站原创或翻译。若要转载但请务必注明出处,尊重他人劳动成果。
转载请注明出处链接 : https://www.inlojv.com/5011.html