0

背景

我正在为我的网站编写一个异步评论系统,在阅读了大量关于如何实现这一点的教程之后,我开始从头开始构建一个。使用 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 行,因此随着页面的增长,用户不会在他们的新评论附近寻找任何地方。

4

2 回答 2

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() 不会有相关的事件处理程序)。

编辑:根据评论使回调可选。使用上面的代码,您可以在没有或没有回调的情况下调用该函数。

于 2009-03-15T03:45:14.157 回答
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 评论。

于 2009-03-15T04:30:16.390 回答