友人C

typecho博客实现ajax评论
前言 系列文章: typecho博客实现pjax instantclick 中文文档 相关文章: Type...
扫描右侧二维码阅读全文
26
2017/07

typecho博客实现ajax评论

前言

系列文章

相关文章

阅读前须知

  1. 以下内容对于实现了pjax效果的站点,可能需要自行增加回调函数。
  2. 以下内容完全适用于实现了instantclick站点
  3. 标有(*)内容为可选内容,可略去不读
  4. 如有疑问可以发送邮件或者直接评论,千万不要加我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) { 
                //这部分内容在第四步中会解释
            }
        })   

深度截图_选择区域_20170726235047.png

获取到ajax请求的数据,从这些数据中找到最新评论的内容,并把该内容插入到当前页面中

如何从ajax成功返回的数据中找到最新评论,我有两个思路:

  1. ajax请求成功返回的数据中寻找到最新的评论插入到当前页面中。
  2. 直接在提交的时候,拿一个变量把用户提交的内容保存起来,然后,直接按照你的评论结构组装成一条评论插入到当前页面中

我是第一种方法,所以以下代码分析均只适用与第一种方法。

  • 第一个问题:理解ajax请求成功后返回的数据是什么东西?

返回的数据是执行提交操作后页面的html代码,换句话说,返回的数据(data)就相当于手动刷新当前页面后的html代码

所以,在返回的数据里面,肯定是可以找到最新评论的!

  • 第二个问题:如何找到最新评论的内容和应该插入到什么位置?

首先你得保证你的评论将较新的的评论显示在前面

其次,我把用户评论简单分成两种:

  1. 母评论(parent):直接评论文章的
  2. 子评论(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

需要的小伙伴直接下载代码,因为每个主题的评论结构有所不同,需要自行修改后才能使用。

最后修改:2018 年 03 月 03 日 07 : 22 PM
如果觉得我的文章对你有用,请随意赞赏

44 条评论

  1. JIElive

    我的问题已经解决了,少了个click_bind()的调用

  2. JIElive

    dalao你好,我用了你的这个ajax评论,倒是嵌套有些问题,具体表现为:
    刷新页面后的第一次评论不能正常嵌套,然后这时不要刷新,接着往后的评论都可以正常嵌套了,是什么原因呃,希望有时间了能到我的小站查看源码帮助一下

  3. 夜落

    为什么文件下载不了!

    1. 友人C
      @夜落

      已经整合到core.min.js 里面了,你可以在里面找下代码 https://www.ihewro.com/usr/themes/handsome/assets/js/core.min.js?v=3.2.12017072603

  4. 尚寂新

    还在吗 用了ajax回复和pjax之后 评论邮件提醒不能用了

    1. 友人C
  5. 尚寂新

    https://www.ihewro.com/usr/themes/handsome/js/ajax_comments.min.js?v=3.2.12017072603
    Path '/usr/themes/handsome/js/ajax_comments.min.js' not found
    文件没了.

  6. 尚寂新

    话说你的instantclick进度条咋自定义的 求教qwq

    1. 友人C
      @尚寂新

      取消掉默认的进度条,然后在instantclick 的两个回调函数里面写开启动画、关闭动画相关代码就可以
      waitchange 分别是这两个回调函数

  7. 一元

    哈哈OωO

    1. 免费新大陆
      @一元

      测试下评论

发表评论