经常在各大论坛或新闻板块详情页面下边看到评论功能,当然不单单是直接发表评论内容那么简单,可以对别人的评论进行回复,别人又可以对你的回复再次评论或回复,如此反复,理论上可以说是没有休止;

从技术角度分析很容易想到运用无限级分类技术存储数据,运用递归获取评论层级结构数据,运用ajax实现评论页面交互,这里用thinkphp框架做个简单的demo练练手,为了简化流程这里第三级评论开始停止回复,当然只要在这个基础上稍作修改就可以实现无限回复功能,主要是view层样式修改较麻烦,需花些时间。

一、效果需求分析:

1.在头部可以直接发布一级评论,最新发表的评论显示在最上面,如下效果图

2.对发表的评论可以回复,回复显示在上级评论下边,形成层级关系,如下效果图

3.页面操作细节:点击某个评论的回复按钮时,显示回复文本输入框,同时其他评论的回复文本输入框消失,当再次点击该回复按钮时,该文本框消失

4.在最后一级评论(这里设置是第三级)关闭回复功能

5.即时显示评论总数

二、实现思路及细节

1.数据表设计

2.controller层关键函数:

(1). 递归获取评论列表

/**
*递归获取评论列表*/protected function getCommlist($parent_id = 0,&$result = array()){ $arr = M('comment')->where("parent_id = '".$parent_id."'")->order("create_time desc")->select(); if(empty($arr)){return array();}foreach ($arr as $cm) { $thisArr=&$result[];$cm["children"] = $this->getCommlist($cm["id"],$thisArr); $thisArr = $cm;     }return $result;}

(2). 展示评论页面的action

public function index(){ $num = M('comment')->count(); //获取评论总数$this->assign('num',$num);$data=array();$data=$this->getCommlist();//获取评论列表$this->assign("commlist",$data);$this->display('index');}

(3).评论页面ajax访问添加评论的action

/**
*添加评论*/public function addComment(){  $data=array();if((isset($_POST["comment"]))&&(!empty($_POST["comment"]))){$cm = json_decode($_POST["comment"],true);//通过第二个参数true,将json字符串转化为键值对数组$cm['create_time']=date('Y-m-d H:i:s',time());$newcm = M('comment');$id = $newcm->add($cm);$cm["id"] = $id;$data = $cm;$num = M('comment')->count();//统计评论总数$data['num']= $num;}else{$data["error"] = "0";}echo json_encode($data);}

3.view层实现

(1). 展示页面的整体结构设计

实际效果:

页面html代码:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"><title>php无限级分类实战————评论及回复功能</title><link rel="stylesheet" type="text/css" href="/Public/css/comment.css" rel="external nofollow" ><script type="text/javascript" src="/Public/js/jquery-1.11.3.min.js" ></script><script type="text/javascript" src="/Public/js/comment.js" ></script>
</head>
<body><div class="comment-filed"><!--发表评论区begin--><div><div class="comment-num"><span>{$num}条评论</span></div><div><div><textarea class="txt-commit" replyid="0"></textarea></div><div class="div-txt-submit"><a class="comment-submit" parent_id="0" style="" href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" ><span style=''>发表评论</span></a></div> </div></div><!--发表评论区end--><!--评论列表显示区begin--><!-- {$commentlist} --><div class="comment-filed-list" ><div><span>全部评论</span></div><div class="comment-list" ><!--一级评论列表begin--><ul class="comment-ul"> <volist name="commlist" id="data">   <li comment_id="{$data.id}">   <div ><div><img class="head-pic" src="{$data.head_pic}" alt=""> </div><div class="cm"><div class="cm-header"><span>{$data.nickname}</span><span>{$data.create_time}</span></div><div class="cm-content"><p>{$data.content}</p></div><div class="cm-footer"><a class="comment-reply" comment_id="{$data.id}" href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >回复</a>   </div> </div>        </div><!--二级评论begin--><ul class="children"><volist name="data.children" id="child" >    <li comment_id="{$child.id}">   <div ><div><img class="head-pic" src="{$child.head_pic}" alt=""> </div><div class="children-cm"><div class="cm-header"><span>{$child.nickname}</span><span>{$child.create_time}</span></div><div class="cm-content"><p>{$child.content}</p></div><div class="cm-footer">    <a class="comment-reply" replyswitch="off" comment_id="{$child.id}" href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >回复</a></div> </div>        </div><!--三级评论begin--><ul class="children"><volist name="child.children" id="grandson" > <li comment_id="{$grandson.id}">   <div ><div><img class="head-pic" src="{$grandson.head_pic}" alt=""> </div><div class="children-cm"><div class="cm-header"><span>{$grandson.nickname}</span><span>{$grandson.create_time}</span></div><div class="cm-content"><p>{$grandson.content}</p></div><div class="cm-footer">    <!-- <a class="comment-reply" comment_id="1" href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >回复</a> --></div> </div>        </div></li></volist></ul> <!--三级评论end--></li></volist></ul> <!--二级评论end--></li></volist>         </ul><!--一级评论列表end--></div> </div><!--评论列表显示区end-->
</div>
</body>
</html>

(2). 单个评论信息div结构代码

<div ><div><img class="head-pic" src="{$data.head_pic}" alt=""> </div><div class="cm"><div class="cm-header"><span>{$data.nickname}</span><span>{$data.create_time}</span></div><div class="cm-content"><p>{$data.content}</p></div><div class="cm-footer"><a class="comment-reply" comment_id="{$data.id}" href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >回复</a>   </div> </div>
</div>

对应的效果图:

对应的css代码:

.head-pic{width:40px;height:40px;
}.cm{position:relative;top:0px;left:40px;top:-40px;width:600px;
}.cm-header{padding-left:5px;
}.cm-content{padding-left:5px;
}.cm-footer{padding-bottom:15px;text-align:right;border-bottom: 1px dotted #CCC;
}.comment-reply{text-decoration:none;color:gray;font-size: 14px;
}

4. JS代码

(1). 提交评论:提交评论的a标签按钮引用了样式comment-submit,在其点击事件中进行ajax操作

$('body').delegate('.comment-submit','click',function(){ var content = $.trim($(this).parent().prev().children("textarea").val());//根据布局结构获取当前评论内容$(this).parent().prev().children("textarea").val("");//获取完内容后清空输入框if(""==content){alert("评论内容不能为空!"); }else{var cmdata = new Object();cmdata.parent_id = $(this).attr("parent_id");//上级评论idcmdata.content = content;cmdata.nickname = "游客";//测试用数据cmdata.head_pic = "/Public/images/default.jpg";//测试用数据  var replyswitch = $(this).attr("replyswitch");//获取回复开关锁属性$.ajax({type:"POST",url:"/index.php/home/index/addComment",data:{comment:JSON.stringify(cmdata)  },dataType:"json",  success:function(data){if(typeof(data.error)=="undefined"){$(".comment-reply").next().remove();//删除已存在的所有回复div //更新评论总数   $(".comment-num").children("span").html(data.num+"条评论");//显示新增评论var newli = "";   if(cmdata.parent_id == "0"){//发表的是一级评论时,添加到一级ul列表中   newli = "<li comment_id='"+data.id+"'><div ><div><img class='head-pic' src='"+data.head_pic+"' alt=''></div><div class='cm'><div class='cm-header'><span>"+data.nickname+"</span><span>"+data.create_time+"</span></div><div class='cm-content'><p>"+data.content+"</p></div><div class='cm-footer'><a class='comment-reply' comment_id='"+data.id+"' href='javascript:void(0);'>回复</a></div></div></div><ul class='children'></ul></li>";    $(".comment-ul").prepend(newli);}else{//否则添加到对应的孩子ul列表中    if('off'==replyswitch){//检验出回复关闭锁存在,即三级评论不再提供回复功能    newli = "<li comment_id='"+data.id+"'><div ><div><img class='head-pic' src='"+data.head_pic+"' alt=''></div><div class='children-cm'><div class='cm-header'><span>"+data.nickname+"</span><span>"+data.create_time+"</span></div><div class='cm-content'><p>"+data.content+"</p></div><div class='cm-footer'></div></div></div><ul class='children'></ul></li>";}else{//二级评论的回复按钮要添加回复关闭锁属性   newli = "<li comment_id='"+data.id+"'><div ><div><img class='head-pic' src='"+data.head_pic+"' alt=''></div><div class='children-cm'><div class='cm-header'><span>"+data.nickname+"</span><span>"+data.create_time+"</span></div><div class='cm-content'><p>"+data.content+"</p></div><div class='cm-footer'><a class='comment-reply' comment_id='"+data.id+"' href='javascript:void(0);' replyswitch='off' >回复</a></div></div></div><ul class='children'></ul></li>";}    $("li[comment_id='"+data.parent_id+"']").children("ul").prepend(newli);}}else{//有错误信息alert(data.error);}}});}});

(2).回复评论:回复评论的a标签按钮引用了样式comment-reply,在其点击事件中进行显示或隐藏评论输入框的操作

//点击"回复"按钮显示或隐藏回复输入框$("body").delegate(".comment-reply","click",function(){if($(this).next().length>0){//判断出回复div已经存在,去除掉$(this).next().remove();}else{//添加回复div$(".comment-reply").next().remove();//删除已存在的所有回复div //添加当前回复divvar parent_id = $(this).attr("comment_id");//要回复的评论idvar divhtml = "";if('off'==$(this).attr("replyswitch")){//二级评论回复后三级评论不再提供回复功能,将关闭属性附加到"提交回复"按钮"divhtml = "<div class='div-reply-txt' style='width:98%;padding:3px;' replyid='2'><div><textarea class='txt-reply' replyid='2' style='width: 100%; height: 60px;'></textarea></div><div style='margin-top:5px;text-align:right;'><a class='comment-submit' parent_id='"+parent_id+"' style='font-size:14px;text-decoration:none;background-color:#63B8FF;' href='javascript:void(0);' replyswitch='off' >提交回复</a></div></div>";}else{divhtml = "<div class='div-reply-txt' style='width:98%;padding:3px;' replyid='2'><div><textarea class='txt-reply' replyid='2' style='width: 100%; height: 60px;'></textarea></div><div style='margin-top:5px;text-align:right;'><a class='comment-submit' parent_id='"+parent_id+"' style='font-size:14px;text-decoration:none;background-color:#63B8FF;' href='javascript:void(0);'>提交回复</a></div></div>";}  $(this).after(divhtml);}});

以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要请关注我的个人主页—知乎专栏PHP7进阶架构师或者请戳这里

jquery实现层级显示 效果图_php运用无限级分类实现评论及回复功能相关推荐

  1. php无极分类非递归_php实现无限级分类(递归方法)

    相信很多学php的很多小伙伴都会尝试做一个网上商城作为提升自己技术的一种途径.各种对商品分类,商品名之类的操作应该是得心应手,那么就可以尝试下无限级分类列表的制作了. 到网上一搜php无限极分类,很多 ...

  2. php递归实现层级树状展开,PHP递归实现层级树状展开,php递归层级树状_PHP教程...

    PHP递归实现层级树状展开,php递归层级树状 本文实例为大家分享了PHP递归实现层级树状展开的主要代码,供大家参考,具体内容如下 效果图: 实现代码: $arr['id'], 'fid' => ...

  3. php修改新闻分类代码,新闻分类录入、显示系统_php

    本系统可以录入标题.内容.图片.相关软件,显示时会根据是否有有图片和相关软件来判断是否显示该项内容,打开页面显示的是最新的一片文章,点击目录会显示之前的文章. 建立channelimages和chan ...

  4. php ci ajax用户登录,使用jQuery和CI显示AJAX调用数据库的数据

    模型似乎和控制器一样工作. AJAX将结果显示为"null",所以我认为这是因为我们需要将数据作为json发送.如何将数据放到正确的格式,并在视图中显示任何想法使用jQuery和C ...

  5. idea包名呈现层级显示

    项目结构视图右上角那个齿轮 第二行菜单,[Compact Middle Packages]不分层级显示,去掉前面的√

  6. 由object元素引出的事件注册问题和层级显示问题

    项目有一个双击监控视频全屏的需求,视频播放使用的是IE下的ActiveX控件,web页面中使用HTML嵌入对象元素object.预期方案如下: 1.在开发ActiveX控件时加入双击事件. 2.通过d ...

  7. php查找顶级分类,php 无限级分类 获取顶级分类ID,php顶级_PHP教程

    php 无限级分类 获取顶级分类ID,php顶级 有这样一个表,id是分类的ID,name是分类名称,pid是上级分类的ID. 现在有个分类ID,程序要找到它上级的上级的上级--分类的ID,简单说就是 ...

  8. php如何对 mysql 中text类型拆分存入一个数组_PHP递归实现无限级分类,可选返回字符串和数组...

    正 文: 在一些复杂的系统中,要求对信息栏目进行无限级的分类,以增强系统的灵活性.那么PHP是如何实现无限级分类的呢?我们在本文中使用递归算法并结合mysql数据表实现无限级分类. 递归,简单的说就是 ...

  9. html下拉框只选择年份和月份,原生jQuery实现只显示年份下拉框

    本文实例为大家分享了jQuery实现只显示年份下拉框的具体代码,供大家参考,具体内容如下 代码: Document 1949 var date = new Date(); var y = date.g ...

最新文章

  1. 【Win32汇编】测试Irvine32库
  2. 在MyEclipse中添加 XML Catalog (xwork-validator dtd )
  3. wireshark 常用命令
  4. RetinaNet+focal loss
  5. c++父类和子类转化致命的代码错误
  6. 开发者实测 M1 芯片报告:除了大型应用程序启动慢点,整体性能优秀!
  7. 如何绘制一幅优雅的列线图
  8. 工厂模式及在Spring中的应用
  9. Linux服务器查看Ip地址
  10. NO 00004 iOS实现打砖块游戏 一 素材的制作
  11. 利用CompletableFuture集齐7龙珠
  12. request_threaded_irq与request_irq
  13. 沪苏浙皖强化网络安全领域威胁情报共享和网络安全事件协同处置机制
  14. 618营销新动向:Swisse年轻化产品教育成电商战场新突破口!
  15. Java发送http的get、post、put请求
  16. STM32F103模拟IIC总线驱动四个VL53L0
  17. 源码分析教程5部曲之1——漫游C语言-杨振平-专题视频课程
  18. 路由器恢复出厂设置上网方式服务器无响应,路由器恢复出厂设置后不能联网了如何解决...
  19. 瓜子二手车 翻页 csv
  20. java反射通俗解释,谁来帮用通俗易懂的语言解释下java的反射机制

热门文章

  1. Microbiome:根系分泌物驱动土壤记忆抵御植物病原菌(作者解读)
  2. 扩增子图表解读1箱线图:Alpha多样性,老板再也不操心的我文献阅读了
  3. R语言ggplot2可视化时间序列散点图、X轴和Y轴都是时间信息、使用as.POSIXct函数自定义指定Y轴的时间范围(setting time limits in y axis)
  4. R语言使用timeROC包计算存在竞争情况下的生存资料多个标记物在相同时间下的cox及协变量分析AUC值、并可视化多个标记物在相同时间下的ROC值、多指标的ROC曲线(Time-dependent R
  5. R语言生成词云(wordcloud)实战
  6. R语言广义线性模型函数GLM、广义线性模型(Generalized linear models)、GLM函数的语法形式、glm模型常用函数、常用连接函数、逻辑回归、泊松回归、系数解读、过散度分析
  7. pandas对dataframe进行排序:单数据列排序、多数据列排序、NA值排序位置、排序算法
  8. R语言使用ggplot2包使用geom_dotplot函数绘制分组点图(双分类变量分组可视化、颜色自定义、添加箱图)实战(dot plot)
  9. R密度聚类之DBSCAN模型
  10. python代码实现插入排序