全站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
