前言
系列文章:
相关文章:
阅读前须知:
- 以下内容对于实现了pjax效果的站点,可能需要自行增加回调函数。
- 以下内容完全适用于实现了instantclick站点
- 标有(*)内容为可选内容,可略去不读
- 如有疑问可以发送邮件或者直接评论,千万不要加我QQ提问
代码分析
ajax的基础知识
这里使用的是jQuery ajax的底层的一个方法:$.ajax()
,执行这个方法的时候,会返回一个创建的XMLHttpRequest
对象。
基本语法:
$.ajax({
url: ,//发送请求的地址
type: ,//请求方式,是post还是get请求
data: ,//要发送到服务器的数据
error: function() {
//请求失败执行的回调函数
},
success: function(data) {
//请求成功执行的回调函数,参数data是请求成功后的页面的纯文本 HTML 代码
}
})
实现步骤
监听comment_form
评论框的提交事件:
$(comment_form).submit(function() {
//提交事件
})
(*) 检查评论内容以及作者邮箱内容是否符合规则(预检):
这段代码比较简单易懂,不再赘述,直接看代码就行了。
发起ajax请求:
就是最基础的$.ajax() 请求:
$.ajax({
url: $(this).attr('action'),//提交表form的action属性
type: $(this).attr('method'),//提交表form的method属性
data: $(this).serializeArray(),//要发送到服务器的数据
error: function() {
//这里写一下提示信息代码即可
},
success: function(data) {
//这部分内容在第四步中会解释
}
})
获取到ajax请求的数据,从这些数据中找到最新评论的内容,并把该内容插入到当前页面中:
如何从ajax成功返回的数据中找到最新评论,我有两个思路:
- 从ajax请求成功返回的数据中寻找到最新的评论插入到当前页面中。
- 直接在提交的时候,拿一个变量把用户提交的内容保存起来,然后,直接按照你的评论结构组装成一条评论插入到当前页面中
我是第一种方法,所以以下代码分析均只适用与第一种方法。
- 第一个问题:理解ajax请求成功后返回的数据是什么东西?
返回的数据是执行提交操作后页面的html代码,换句话说,返回的数据(data)就相当于手动刷新当前页面后的html代码
所以,在返回的数据里面,肯定是可以找到最新评论的!
- 第二个问题:如何找到最新评论的内容和应该插入到什么位置?
首先你得保证你的评论将较新的的评论显示在前面
。
其次,我把用户评论简单分成两种:
- 母评论(parent):直接评论文章的
- 子评论(children):评论文章中的某条评论
我们先来看如何找到最新评论的内容:
其实很简单:typecho生成commentID的时候总是越来越大的,所以只要找到数据中最大的那个commentID就是用户刚才评论的最新评论了!
代码就是:
new_id = $(comment_list, data).html().match(/id=\"?comment-\d+/g).join().match(/\d+/g).sort(function(a, b) {
return a - b
}).pop();
但是其实还是存在一个问题的:如果你启用了评论分页功能,由于typecho显示最新评论总是在第一页,所以当用户不在第一页发出了母评论
,那么从数据(data)中找到的ID最大的评论并不是最新评论,
这个时候,发送ajax请求成功后,就没必要向当前页面插入评论,因为最新评论再第一页。
if ($('.page-navigator .prev').length && parent_id == ""){
new_id = '';
}//做一个判断
...
if (new_id)//new_id不为空的时候才会插入
$('#' + parent_id + " .comment-children .comment-list").prepend(data);
接下来就是插入的位置问题:
其实很简单,如果是母评论,直接插入到comment_list
的最前面即可:
$(comment_list).prepend(data);
如果是子评论,要在监听页面中的回复链接
,当鼠标点击回复按钮的时候,通过父元素的父元素(根据个人的评论结构而定),找到回复当前的评论ID(parentID):
$(comment_reply + ' a').click(function() { // 回复
parent_id = $(this).parent().parent().parent().parent().attr("id");
$(textarea).focus();
});
$('#cancel-comment-reply-link').click(function() { // 取消
parent_id = '';
});
插入的位置就是回复当前评论的最前面就行了:
if (parent_id) {
data = $('#comment-' + new_id, data).hide(); // 取新评论
if ($('#' + parent_id).find(".comment-children").length <= 0) {
$('#' + parent_id).append("<div class='comment-children list-unstyled m-l-xxl'><ol class='comment-list'></ol></div>");
}
if (new_id) //new_id不为空的时候才会插入
$('#' + parent_id + " .comment-children .comment-list").prepend(data);
//console.log('该评论为子评论,parent_id:' + parent_id);
parent_id = '';
//console.log(data);
}
代码分析到这里就结束了!
handsome主题已经内置该部分代码,并且做了优化,在外观设置——高级设置
中启用即可。
代码下载
我把相关代码写到了一个文件里ajax_comment.min.js
需要的小伙伴直接下载代码,因为每个主题的评论结构有所不同,需要自行修改后才能使用。
52 条评论
我试一下效果
OωO 看看效果如何
你的主题集成了没有 我又想重新弄博客了。。
集成了呀!
ajax不是还可以用来实现刷新前可再编辑,只有当离开页面或刷新页面才POST评论么?
有计划实现这样的功能?
可以是可以,但是懒得了,感觉这样意义不是特别大(#滑稽)
Typecho 缺的其实是一个 JSON API。如果有就不用这么麻烦了,直接输出返回的数据
你的表情PJAX怎么弄的?我弄了老半天刷新下就能显示,一到PJAX瞬间爆炸
instantclick比pjax要简单很多,因为,instantclick在切换页面的时候js仍然会被加载,少了pjax的回调的问题(/ω\)
我的这个主题用了PJAX,改成InstantClick可能不是很好改,所以我改了老半天没头绪来问你了(。•ˇ‸ˇ•。)
还有一个方法可以重载
试试jq的这个函数(加在pjax完成后)
'''
$.getScript("yourjs");
'''
能GET到JS了,可是还是出现了这种错误(╯‵□′)╯︵┴─┴:
Cannot set property 'innerHTML' of undefined
你可以试试直接把owo的html结构写在评论,只用它的样式,自己写几个简单的js就行我就这么干的
哦,我试试
这个,我感觉只要把owo.js核心内容封装成一个函数,然后在pjax结束的时候回调这个函数应该就可以
但是具体实现起来不造行不行了(╯°A°)╯︵○○○
一说封装函数还真的有用|´・ω・)ノ
我试了试发现评论回复有问题,直接放在最顶上,没有放到母评论下,可以帮忙看看吗|´・ω・)ノ
恩,你可以把地址的账号信息发到我邮箱里面,我看一下吧(ó﹏ò。)
或者联系我QQ吧
InstantClick怎么改变一些class
比如:首页 的 class 为 home,文章页为 post
这个可以通过php的判断
比如:
ajax不是很懂,小白来的,哈哈。有点无从下手呀,研究一下你的ajax_comment.min.js看看能否明白。
懂JavaScript的语法应该就没问题|´・ω・)ノ
如果点击提交评论以后链接中会多出 /comment-page-6#comment-3836 这一块,我们可以根据它直接找到最新提交的数据,即使不在第一页
你说的那个分页评论bug,我有个好的想法,在你的判断结束后,这样处理下取得.prev a的链接地址,将里面的页码数字换成1,然后将得到的地址在赋予回去,然后用js点击,因为用了预加载那个js,所以即使这样处理背景音乐也是不会断掉的
( ,,´・ω・)ノ"(´っω・`。) 等下研究下
试试看什么效果
|´・ω・)ノ是不是还不错!