WordPress评论ajax动态加载,解决静态缓存下评论不更新问题

这是一个历史遗留问题,自从博客部署了 PHP 纯静态缓存之后,所有页面都是 html 静态内容了,而且在七牛 CDN 静态分离之后,速度更是达到极致!

不过也带来不少疑难问题,在之前写的《启用 WP Super Cache 纯代码版本之后的一些优化措施》一文中已经总结一些解决办法。其中为了解决用户无法看到最新回复的问题,我也想了多个办法,比如成功提交评论就会删除该页缓存、右下角集成清理缓存按钮等。在我多次改进之后,已经趋向于完美,而且这个 php 缓存优化也是张戈博客有偿服务最受欢迎的项目之一。

前不久,有朋友拿我的网站练手,用大量代理 IP 对我的博客进行 DDos 攻击,无奈之下博客临时转入到百度云加速。转入之后,如果把云加速的页面缓存也打开,那么就有了 2 层缓存:【CDN 节点的 html 缓存】和【服务器的 html 缓存】。那么我之前写的ajax 清理缓存以及评论删除缓存失去了效果,因为只能删除本地的 html 缓存,而 CDN 节点的缓存百度并未提供 API 控制接口,所以用户看到的还是缓存内容!

当然,不是强迫症的话,直接关闭百度的页面缓存就可以了!但这只是逃避问题,而没有解决问题!所以,本文就分享一下,强迫症是如何解决这个非必须问题的。

一、自动动态加载评论

这是我最初想到的、而且是老早就想实现一种方案:当静态的 html 页面加载时,评论部分实时从数据库动态拉取数据,由于是纯静态下的 html 页面,所以这个功能需要 JS+Ajax 来实现。

①、php 评论动态拉取接口代码

<?php
if ('comment_list.php' == basename($_SERVER['SCRIPT_FILENAME']) && !isset($_POST['post_id'])) {
    header("content-type:text/html; charset=utf-8");
    echo '您好!请不要直接访问这个页面!';
    exit();
}
require('../wp-blog-header.php');
header("Content-type: text/html;charset=UTF-8");
header('HTTP/1.1 200 OK');
$comments = get_comments(array(
	'post_id' => $_POST['post_id'],
	'status' => 'approve'
));
echo '<ol class="commentlist">';
wp_list_comments('type=comment&reverse_top_level=true&page=0&callback=mytheme_comment&end-callback=mytheme_end_comment',$comments);
echo '</ol>';
?>

Ps:代码的原理就不赘述了,主要用到 wp_list_comments 内置函数,感兴趣的可以自行了解下。

以上代码保存为 php 文件,比如 ajax-comments.php,保存到网站根目录,备用。

②、Ajax 评论请求代码

<script type="text/javascript">
/* 将函数放置到ready里面,页面加载后自动执行 */
jQuery(document).ready(function($){
     Ajax_Comments();   
});
/* Ajax请求,分开写方便调用 */
function Ajax_Comments(){
$.ajax({
    type: "POST",
    url: location.origin+"/ajax-comments.php",
    data:{"post_id":<?php echo $post->ID;?>},
    dataType: "html",
    success: function(out){
        /* 用实时拉取的内容替换原来的内容 */
        $('.commentlist').html($(out).fadeIn(500));
    }
});
}
</script>

以上代码可以直接贴到网站的 footer.php 当中。如果你要添加到 js 文件中,请除去首尾的 script 标签,而且 post_id 值需要在外部通过 php 动态定义(搞不清的还是直接贴 footer 吧)!

特别说明下,2 段代码中的【.commentlist】是指评论列表的 class,比如知更鸟主题的评论列表的是<ol class="commentlist">评论列表</ol>,实际上请根据主题的评论列表 class 或 ID 来自行修改!

部署无误之后,每次页面加载都会动态去拉取一次最新的评论,并呈现给用户。

优点:每次打开页面用户都能看到最新评论; 缺点:每次打开页面都会动态拉取评论,降低了纯静态效果,拉取的评论分页有点误差(影响不大)。

二、手动动态刷新评论

这个方法灵感源自网络上流行的评论分页 Ajax 加载:点击评论的下一页,不会刷新整个页面,而是通过 ajax 拉取被点击那个分页的全部内容,然后找到评论部分并加载。

简单解释下原理:

比如,张戈博客的留言板,有 100 页评论,那么第 99 页的评论地址应该是:http://zhangge.net/liuyan/comment-page-99/,当点击【99】这个分页链接时,将触发 ajax 函数,先隐藏当前分页的所有评论,然后 ajax 拉取第 99 页的内容,然后将评论部分加载出来,实现不刷新页面来加载评论。

分析了这个过程,我们可以发现一个特征关键字,那就是分页地址后面的 comment-page-xx !这是个好东西,因为我可以在云加速和本地的缓存中排除这个关键词的缓存即可!也就说,浏览器直接访问带comment-page-xx这类关键词的地址,就略过缓存,加载动态内容!

因此,当我们部署了 ajax 评论分页,点击其他分页将会显示非缓存内容!但是这还不是我需要的,因为我想要当前页面也实现动态评论。也许聪明人会说,你点到其他评论分页,再点回来不就好了嘛?

确实,实现 ajax 评论分页后,我点到其他评论分页,然后再点回来,确实可以实现评论刷新,但是却用了 2 次点击!

好,下面我们换个角度,既然 comment-page-xx 是动态页面,那么 comment-page-1 肯定也是动态页面咯!

于是就有 2 种情况:第一种,文章评论数量还不够生成分页,那这时候只要拉取 comment-page-1 就可以了;第二种,评论已经存在分页,那么只要拉取这个 comment-page-【页码】即可,所以 ajax 拉取之前,我们只要通过 js 判断来决定要拉取的目标地址即可。

那么,js 如何判断评论是否有分页了呢?很简单,先分析下网页代码:

可以发现分页是有分页对应的 class 的,那么 js 只要判断这个 class 是否存在就好啦!而且我还可以发现当前的分页和其他分页的 class 还是不一样的:当前分页的 class 是【page-numbers current】,而 其他分页则是【page-numbers】,如以此来,我们还可以用 js 代码 $('.page-numbers.current').html() 获得当前分页的页码!!!

那问题就好解决了,我们只要先判断是否存在分页,然后根据不同情况抓取不同的目标地址即可!

下面开始分享代码:

/* 评论ajax获取函数 */
function Ajax_Comments(){
    $.ajax({
        type: "GET",
        url: ajax_url,
        beforeSend: function(){
            /* 触发后移除评论列表、评论分页及评论统计(不清楚的可参考张戈博客的评论ID元素) */
            $('.navigation_c').remove();
            $('.commentlist').remove();
	    $('#comments').remove();
            /* 显示正在加载中效果 */
            $('#loading-comments').slideDown();
            /* 这里判断评论开启并没有评论的情况,sofa是我定义的抢沙发DIV */
            if($('.sofa').html() == undefined && $('.nocomments').html() == undefined ){
                $body.animate({scrollTop: $('.refresh').offset().top - 65}, 800 );
            /*  这里判断评论已关闭,nocomments是提示本文评论已关闭的div */
            } else if ($('.nocomments').html() != undefined){
                alert('很抱歉!本文评论已关闭。您可以到留言板</a>畅所欲言。');
                return false;
            }
        },
        dataType: "html",
        success: function(out){
            /* 在ajax拉取内容中查找评论列表部分 */
	    commentlist = $(out).find('.commentlist');
            /* 如果没有评论,则提示抢沙发 */
            if(commentlist.length == 0) {
                $('#loading-comments').hide();
                alert('暂无评论,您可以抢沙发哟~!;');
                return false;
            /* 如果有评论,则移除抢沙发模块 */
            } else {
                $('#sofa').remove();
            }
            /* 获取评论统计DIV模块,有的主题可能没有 */
            comments = $(out).find('#comments'); 
            /* 获取评论分页DIV模块 */
            nextlink = $(out).find('.navigation_c');
            $('#loading-comments').slideUp('fast');
            /* 将评论统计输出到(加载中)模块的后面,并移除[加载中]模块 */
	    $('#loading-comments').after(comments.fadeIn(500));
            /* 将评论列表输出到评论统计模块的后面 */
	    $('#comments').after(commentlist.fadeIn(500));
            /* 将评论分页输出到评论列表的后面,完成本次加载 */
            $('.commentlist').after(nextlink);
        }
    });  
}
 
/* 评论ajax分页 */
$('.page-numbers').live('click', function(e){
    e.preventDefault();
    if ($(this).attr('href') != undefined) {
        ajax_url = $(this).attr('href');
    } else {
        /* 点击当前分页页码也可以刷新评论 */
        ajax_url = page_url+"/comment-page-"+$('.page-numbers.current').html()+"/#comments";
    }
    Ajax_Comments()
});
 
/* 手动刷新评论 */
function refresh_Comments(){
    /* 根据文章是否存在分页,定义不同的抓取地址 */
    if ($('.page-numbers.current').html() != undefined) {
        /* 如果存在分页,则抓取当前分页地址 */
        ajax_url = page_url+"/comment-page-"+$('.page-numbers.current').html()+"/#comments";
    } else {
        /* 如果没有分页,则抓取comment-page-1 */
        ajax_url = page_url+"/comment-page-1/#comments";
    }
    Ajax_Comments();
}
 
/* 将评论刷新函数绑定到ID为refresh的点击事件上 */
$(function(){ 
    $("#refresh").click(function(){
        refresh_Comments();
    }); 
});

使用方法很简单,把这个代码添加到主题已有的 js 中,然后在任意位置新增一个 ID 为 refresh 的 html 元素即可,比如:

<div id="refresh">刷新评论</div>

Ps:这个代码参考修改自:《WordPress Ajax 评论分页 | Kayo's Melody》,因此如果没看懂 ajax 评论分页,本文分享的也会看得稀里糊涂的,尤其是代码中的 ID 元素,不同主题是不一样的。

本文分享的方法和思路,如果不是真正需要,我想会看得很痛苦,因为我写的也很痛苦!很多地方不好解释,因为你没有需求,就可能看不懂!!但是,只要是我用心折腾过的功能,我都想分享出来,网络这个林子那么大,不可能就没有同样需求的人吧?!有时候,【解决思路】真心比【实现代码】来的更加难得!

这种看似很复杂的文章,实际上,光看文章是很费解的,个人建议结合自己的需求,然后对比张戈博客的页面源代码去参考,会更容易理解一些。

好了,废话说了够多了,还是那句话,文章是分享给真正有需要的人,没有需求,又说不出个甲乙丙丁的人,建议不要在本文浪费口水,说三道四比较好!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏desperate633

深入理解--异步和非阻塞同步和阻塞异步和非阻塞

异步和非阻塞的概念实际上已经出现了很长一段时间。但是异步真正开始流行起来,是因为AJAX技术逐渐成为主流的web开发技术。非阻塞的概念真正流行起来,是当java...

944
来自专栏耕耘实录

五方法破解Linux(CentOS7.4)系统的root密码

版权声明:本文为耕耘实录原创文章,各大自媒体平台同步更新。欢迎转载,转载请注明出处,谢谢

1822
来自专栏数据库新发现

快讯:Oracle 发布了传闻已久的 18.3 RPM 安装版本

关于 Oracle 发布数据库 RPM 安装版本的传闻已经有好几年了,今天 Oracle 终于发布了这个传说中、被期待的安装包,在 OTN 上已经可以下载 Li...

1064
来自专栏信安之路

Google Calaboratory 的另一个 XSS 漏洞

三个月以前,我写了一篇文章来介绍我在 Google Colaboratory 上发现的一个 XSS 漏洞,这篇文章是对前文的一些扩展,并且展示了我在同一个 we...

1944
来自专栏友弟技术工作室

云原生概念

1.8K5
来自专栏IT技术精选文摘

缓存在分布式系统中的应用

缓存是分布式系统中的重要组件,主要解决高并发,大数据场景下,热点数据访问的性能问题。提供高性能的数据快速访问。 一、缓存概述 缓存是分布式系统中的重要组件,主要...

3609
来自专栏Java帮帮-微信公众号-技术文章全总结

Maven 核心原理解析(1)

Maven 是每一位Java工程师每天都会接触的工具, 但据我所知其实很多人对Maven理解的并不深, 只把它当做一个依赖管理工具(下载依赖、打包), Mave...

53910
来自专栏数据和云

快讯:Oracle 发布了传闻已久的 18.3 RPM 安装版本

关于 Oracle 发布数据库 RPM 安装版本的传闻已经有好几年了,今天 Oracle 终于发布了这个传说中、被期待的安装包,在 OTN 上已经可以下载 Li...

1183
来自专栏web

vue.js环境搭建

2413
来自专栏逢魔安全实验室

某移动应用安全加固与脱壳技术研究与实例分析

6118

扫码关注云+社区

领取腾讯云代金券