个人网站留言页面(前端jQuery编写、后台php读写MySQL)
前端之家收集整理的这篇文章主要介绍了
个人网站留言页面(前端jQuery编写、后台php读写MySQL),
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
首先,上个人网站的留言页面,大家可以看看效果:留言板
前端为了省事,使用jQuery编写,后台使用PHP简单读写MysqL数据库。
数据库设计和实现思路
数据库创建了一个表:comments,结构如下图:
全部评论(包括文章评论回复,留言板)都写在同一张表中,不同的评论区用字段belong区分
同一个评论区里,parent为0表示为评论,parent为某值时表示为哪个评论的回复,思路不复杂。
注意,这里并不讲CSS,大家根据自己的需要定制,现在开始封装:
我们根据自己的需要定下功能,首先我的网站并没有实现消息提醒,即时通讯的功能,所以评论回复并不会提示站长或者用户,只会对留言区产生效果,所以我们只要简单实现以下功能:
1、显示评论列表
2、能够提交评论
3、进行回复
我们将评论的功能封装成一个类,通过实例化就能创建不同的评论区,所以不难想到,
实例化的时候我们需要传入的参数可能有:评论区的id、获取评论的PHP地址,提交评论的PHP地址。
所以我们可以猜想实例化评论区的代码可能为:
Box'),//你想要将这个
评论放到
页面哪个元素中
id: 0,getCmtUrl: './
PHP/getcomment.
PHP',setCmtUrl: './
PHP/comment.
PHP'
})
当然,我是在Comment类上定义一个静态方法
Box'),id: 0,setCmtUrl: './
PHP/comment.
PHP'
})
大同小异,只是初始化的地方不同而已
var fn = Comment.prototype;
Comment.allocate = function(options){
var oCmt = new Comment(options);
if (oCmt.belong == undefined || !oCmt.getCmtUrl || !oCmt.setCmtUrl) {
return null;
};
oCmt.init(options);
return oCmt;
};
里面的变量和方法我们慢慢解释,如果你不定义一个allocate方法,那么可以写成:
var fn = Comment.prototype;
变量先不说,像我都是先写功能函数,然后需要添加属性变量再回头来添加,我们只需要看到构造函数最后执行了:
this.init(options)
从名字可以看出是初始化函数。
内容放进容器
this.parent.html(this.body);
//初始化事件
this.initEvent();
//
获取列表
this.getList();
};
fn为Comment.prototype,只说一次,下面就不再说了。
初始化就是有4个工作要做,从代码注释可以看出,现在一个一个讲解
initNode函数
从名字可以看出主要初始化节点或者缓存dom
Box
if (!!options.parent) {
this.parent = options.parent[0].nodeType == 1 ? options.parent : $('#' + options.parent);
};
if (!this.parent) {
this.parent = $('div');
$('body').append(this.parent);
}
//init content
this.body = (function(){
var strHTML = '' +
'
' +
'
' +
'
';
return $(strHTML);
})();
//init other node
this.text = this.body.find('.cmt-text').eq(0);
this.cmtBtn = this.body.find('.u-button').eq(0);
this.noCmt = this.body.find('.no-cmt').eq(0);
this.cmtList = this.body.find('.cmt-list').eq(0);
this.loading = this.body.find('.u-loading1').eq(0);
this.pager
Box = this.body.find('.pager-
Box').eq(0);
};
代码中我们可以看出:
this.parent : 保存的是容器节点
this.body : 保存的是评论区的html
this.text : 保存的是评论的textarea元素
this.cmtBtn : 保存的是提交按钮
this.noCmt : 保存的是没有评论时的文字提醒
this.cmtList : 保存的是列表的容器
this.loading : 保存的是加载列表时的loading GIF图片
this.pagerBox : 需要分页时的分页器容器
js上没有难点,都是一些jQuery的方法
将内容放进容器中
this.parent.html(this.body)
这个没什么好讲的,很简单,这时我们的评论组件应该在页面显示了,只是现在没有加载评论列表,也不能评论,下面先讲加载评论列表
getList 函数
首先是初始化列表,清空,显示加载gif图,隐藏没有评论的提醒字样,做好准备就发起ajax请求。
思路是用PHP将该评论区的留言全部弄下来,在前端再来整理,ajax请求为:
fn.getList = function(){
var self = this;
this.resetList();
$.ajax({
url: self.getCmtUrl,type: 'get',dataType: 'json',data: { id: self.belong },success: function(data){
if(!data){
alert('获取评论列表失败');
return !1;
};
//整理评论列表
self.initList(data);
self.loading.css('display','none');
//显示评论列表
if(self.lists.length == 0){
//暂时没有评论
self.noCmt.css('display','block');
}else{
//设置分页器
var total = Math.ceil(self.lists.length / self.offset);
self.pager = new Pager({
index: 1,total: total,parent: self.pager<a href="/tag/Box/" target="_blank" class="keywords">Box</a>[0],onchange: self.doChangePage.bind(self),label:{
prev: '<',next: '>'
}
});
}
},error: function(){
alert('获取评论列表失败');
}
});
};
get形式,然后传送id过去,得到了的数据希望是列表数组。
PHP的内容不讲,下面贴出sql语句:
$value) {
$id = $value['id'];
$username = $value['username'];
$time = $value['time'];
$content = $value['content'];
$parent = $value['parent'];
$str .= <<<end
{
"id" : "{$id}","parent" : "{$parent}","username" : "{$username.'","time" : "{$time}","content" : "{$content}","response" : []
}
end;
}
$str = substr($str,-1);
$str .= ']';
echo $str;
获得的是json字符串,jQuery的ajax可以将它转为json数据,获得的数据如下:
如果加载成功,那么我们得到的是一堆的数据,我们现在是在success回调函数里,数据需要整理,才能显示,因为现在所有的评论回复都属于同一层。
initList 函数
this.lists = []; //保存
评论列表
this.keys = {}; //保存
评论id和index对应表
var index = 0;
//遍历处理
for(var i = 0,len = data.length; i < len; i++){
var t = data[i],id = t['id'];
if(t['parent'] == 0){
this.keys[id] = index++;
this.lists.push(t);
}else{
var parentId = t['parent'],parentIndex = this.keys[parentId];
this.lists[parentIndex]['response'].push(t);
}
};
};
我的思路就是:this.lists放的都是评论(parent为0的留言),通过遍历获取的数据,如果parent为0,就push进this.lists;否则parent不为0表示这是个回复,就找到对应的评论,把该回复push进那条评论的response中。
但是还有个问题,就是因为id是不断增长的,可能中间有些评论被删除了,所以id和index并不一定匹配,所以借助this.keys保存id和index的对应关系。
遍历一遍就能将所有的数据整理好,并且全部存在了this.lists中,接下来剩下的事情就是将数据变成html放进页面就好了。
显示
评论列表
if(self.lists.length == 0){
//暂时没有
评论
self.noCmt.css('display','block');
}else{
//设置
分页器
var total = Math.ceil(self.lists.length / self.offset);
self.pager = new Pager({
index: 1,label:{
prev: '<',next: '>'
}
});
}
这是刚才ajax,success回调函数的一部分,这是在整理完数据后,如果数据为空,那么就显示“暂时没有评论”。
否则,就设置分页器,分页器我直接用了之前封装的,如果有兴趣可以看看我之前的文章:
面向对象:分页器封装
简单说就是会执行一遍onchange函数,默认页数为1,保存在参数obj.index中
showList函数
/
生成一条评论字符串 /
function oneLi(_obj){
var str1 = '';
//处理回复
for(var i = 0,len = _obj.response.length; i < len; i++){
var t = _obj.response[i];
t.content = t.content.replace(/\<\;/g,'<');
t.content = t.content.replace(/\>\;/g,'>');
str1 += '<li class="f-clear"><table>
<tr><td>' +
'<span class="username">' + t.username + ':</td><td>' +
'<span class="child-content">' + t.content + '</td></tr></table>' +
''
}
//处理
评论
var headImg = '';
if(_obj.username == "kang"){
headImg = 'kang_head.jpg';
}else{
var index = Math.floor(Math.random() * 6) + 1;
headImg = 'head' + index + '.jpg'
}
_obj.content = _obj.content.replace(/\<\;/g,'<');
_obj.content = _obj.content.replace(/\>\;/g,'>');
var str2 = '<li class="f-clear">' +
'<div class="head g-col-1">' +
'<img src="./img/head/' + headImg + '" width="100%"/>' +
'
' +
'<div class="content g-col-19">' +
'<div class="f-clear">' +
'<span class="username f-float-left">' + _obj.username + '' +
'<span class="time f-float-left">' + _obj.time + '' +
'