我正在为我的网站编写异步评论系统,在阅读了大量关于如何实现这一目标的教程后,我开始从头开始构建一个。使用JSON请求提取注释并使用Javascript(jQuery)显示。当用户添加新注释时,它会通过环节,最后通过AJAX发送到后端,并将其添加到数据库中。在AJAX请求的成功部分,我让脚本清空注释,然后重新生成新列表(包括新帖子)并重新显示它们。
虽然这一切都很好,但由于它使页面缩短了很长时间,因此它会让用户查看页面的时间更长。我想让它重新调整页面,直到评论列表的末尾(添加评论表单的位置)。它还重新启用了添加按钮,该按钮在点击它时被禁用,以防止不耐烦的人发送垃圾邮件。
$('#commentList').empty();
getComments('blog', $('input#blogId').val());
window.location = "#addComment";
$('#comAdd').removeAttr('disabled');
虽然这在理论上运作良好且良好,但似乎浏览器在getComments函数完成之前已经超前并处理window.location。所以我再读一遍并用谷歌搜索它似乎人们说(对于类似的问题)使用回调函数,所以我提出了这个:
$('#commentList').empty();
getComments('blog', $('input#blogId').val(), function() {
window.location = "#addComment";
$('#comAdd').removeAttr('disabled');
});
根据FireFox,这不会产生任何javascript错误,但回调函数中的任何内容都不起作用,它不会重新启用按钮,也不会更改window.location。
有什么想法吗?更好的方法去做吧?我有一个我似乎无法看到的明显错字吗?
谢谢!
我的印象是回调函数是你可以使用的标准函数。
function getComments(type, id)
{
$.getJSON("/ajax/"+type+"/comments?jsoncallback=&id="+id, function(data) {
for (var x = 0; x < data.length; x++)
{
var div = $("<div>").addClass("comment").appendTo("#commentList");
var fieldset = $("<fieldset>");
var legend = $("<legend>").addClass("commentHeader");
if ( data[x].url == "" )
{
legend.text((x+1) + ' - ' + data[x].name);
}
else
{
$("<a>").attr({href: data[x].url}).text((x+1) + ' - ' + data[x].name).appendTo(legend);
}
legend.appendTo(fieldset);
$("<div>").addClass("date").text(data[x].timestamp).appendTo(fieldset);
$("<p>").addClass("comment").text(data[x].content).appendTo(fieldset);
fieldset.appendTo(div);
}
});
}
在文档就绪时调用此方法。拉出所有注释并在#commentList div中显示它们。当用户提交他/她的评论时,它会向PHP脚本执行一个AJAX请求,该脚本会将新评论添加到数据库中,一旦成功,我就会这样:
$('#commentList').empty();
getComments('blog', $('input#blogId').val());
window.location = "#addComment";
$('#comAdd').removeAttr('disabled');
删除页面中的所有评论。 使用JSON再次请求注释(包括用户新注释)。 将页面移动到#addComment锚点,这是他们的新评论将显示的位置。 重新启用添加评论按钮。
问题是浏览器在getComments函数完成之前执行window.location行渲染所有注释,因此随着页面的增长,用户看不到任何靠近新注释的位置。
答案 0 :(得分:2)
我希望这里的问题是你的getComments()函数(需要更多详细信息)。你提供的第三个参数是回调,但该函数实际上是否使用回调?它在做什么?
某些jQuery函数提供回调,但这不是自动功能。如果您正在等待用户输入评论,则需要在他们点击“完成”或其他任何操作时触发相关事件。
好的,试试这个:
function get_comments(type, id, callback) {
$.getJSON("/ajax/"+type+"/comments?jsoncallback=&id="+id, function(data) {
for (var x = 0; x < data.length; x++) {
var div = $("<div>").addClass("comment").appendTo("#commentList");
var fieldset = $("<fieldset>");
var legend = $("<legend>").addClass("commentHeader");
if ( data[x].url == "" ) {
legend.text((x+1) + ' - ' + data[x].name);
} else {
$("<a>").attr({href: data[x].url}).text((x+1) + ' - ' + data[x].name).appendTo(legend);
}
legend.appendTo(fieldset);
$("<div>").addClass("date").text(data[x].timestamp).appendTo(fieldset);
$("<p>").addClass("comment").text(data[x].content).appendTo(fieldset);
fieldset.appendTo(div);
if (typeof callback != 'undefined') {
callback();
}
}
});
}
注意:这里的区别在于第三个参数提供给get_comments(),这是一个回调函数,它将在$ .getJSON()回调结束时调用。那将为您提供您想要的正确订单。
我可能还建议不要像这样构建HTML,但要在页面中包含它,并在必要时隐藏/取消隐藏它。它往往比动态HTML更具性能并且问题更少(例如新的HTML,除非你使用$()。live()将没有相关的事件处理程序。)
编辑:根据评论使回调可选。使用上面的代码,您无需回调即可调用该函数。
答案 1 :(得分:0)
简单。重新启用按钮并在收到请求后转到锚点并处理信息。像这样:
function getComments(type, id)
{
// ADDED
$('#commentList').empty();
$.getJSON("/ajax/"+type+"/comments?jsoncallback=&id="+id, function(data) {
for (var x = 0; x < data.length; x++)
{
var div = $("<div>").addClass("comment").appendTo("#commentList");
var fieldset = $("<fieldset>");
var legend = $("<legend>").addClass("commentHeader");
if ( data[x].url == "" )
{
legend.text((x+1) + ' - ' + data[x].name);
}
else
{
$("<a>").attr({href: data[x].url}).text((x+1) + ' - ' + data[x].name).appendTo(legend);
}
legend.appendTo(fieldset);
$("<div>").addClass("date").text(data[x].timestamp).appendTo(fieldset);
$("<p>").addClass("comment").text(data[x].content).appendTo(fieldset);
fieldset.appendTo(div);
}
// ADDED
window.location = "#addComment";
$('#comAdd').removeAttr('disabled');
});
}
个人意见:为什么不从特定日期获取评论,而不是提取所有评论?加载页面时,在响应中包含服务器时间。 Javascript使用它来查询幕后(自动检查新注释)。 JSON响应包括新的服务器时间,用于下一个响应。
您将如何处理已删除的评论?简单:在数据库表中有一个deleted_on列,查询它,并在JSON响应中将其与新帖子一起吐出。
建议:代替#addcomment
,ID按时间戳注释。