【问题标题】:Javascript Array Crossbrowser issuesJavascript 数组跨浏览器问题
【发布时间】:2013-11-08 15:49:42
【问题描述】:

我正在开发一个简单的 Web 应用程序,用户可以在其中按时间顺序评论文章(如博客文章中的 cmets)。每条评论都有一个时间戳。我将KnockoutJS 用于客户端视图模型,并且由于IE9 中日期对象的问题,我使用MomentJS 进行跨浏览器时间戳解析(每个评论的时间戳属性实际上是MomentJS 生成的对象)。数据以 JSON 格式从 REST 端点传到客户端,并在 Knockout 视图模型中实例化。我的文章模型的构造函数看起来像这样(缩短):

GC.ko.modelArticle = function (a) {
    this.Id = ko.observable(a.Id);
    this.Title = ko.observable(a.Title).extend({ required: true, minLength: 3 });
        :     //some more Properties
    this.Comments = ko.observableArray();
    if (util.isDefined(a.Comments)) {
        for (var i = 0; i < a.Comments.length; i++) {
            this.Comments.push(new GC.ko.modelComment(a.Comments[i]));
        }
    }
    this.Comments.sort(function (left, right) {
        return left.Timestamp == right.Timestamp ? 0 : (left.Timestamp < right.Timestamp ? -1 : 1);
    });
};

如您所见,如果 JSON (a) 包含 cmets,则会将它们推送到 Knockout observableArray。之后我按时间升序对数组进行排序,以便 UI 中较旧的注释出现在较新的注释之后。

在 Firefox 和 Chrome 中,数组按升序排序。

在 IE9 中是降序排列的。

这是因为

  • Array().push() 函数的跨浏览器问题
  • 或 Array().sort() 函数,
  • 或者因为 Knockout observable Arrays 存在排序问题,
  • 还是因为我的代码中有错误?

编辑: comment.Timestamp 是一个 Knockout Observable。我尝试了两种变体:

首先返回一个普通的 Javascript 日期对象(在 IE 中有时间戳解析问题,所以我不得不修改它):

this.Timestamp = ko.observable(c.Timestamp)

秒回片刻对象:

this.Timestamp = ko.observable(moment(c.Timstamp)
  • 'c' 是评论的 JSON

编辑 2: 事实证明,Knockout 2.2.1 中 observableArray() 的 sort() 函数似乎是问题所在。我将代码修改为以下内容(首先对普通的 javascript 数组进行排序,然后将元素推送到 KO Observable 数组),现在一切正常。代码如下:

GC.ko.modelArticle = function (a) {
    this.Id = ko.observable(a.Id);
    this.Title = ko.observable(a.Title).extend({ required: true, minLength: 3 });
        :     //some more Properties
    this.Comments = ko.observableArray();
    if (util.isDefined(a.Comments)) {
        a.Comments.sort(function(left,right) {
            return left.Timestamp == right.Timestamp ? 0 : (left.Timestamp < right.Timestamp ? -1 : 1);
        });

        for (var i = 0; i < a.Comments.length; i++) {
            this.Comments.push(new GC.ko.modelComment(a.Comments[i]));
        }
    }
};

【问题讨论】:

  • 试试return +right.Timestamp - left.Timestamp
  • 更简单更优雅的排序语句,不幸的是,结果数组在 IE9 中仍然以相反的方式排序。不过谢谢!不过我会这样简化。
  • GC.ko.modelComment的结构是什么?它或 Timestamp 是可观察的,还是它们只是普通的 JS 属性?
  • @Paul 我尝试了两种变体,都带有淘汰的可观察值。第一个只是“this.Timestamp = ko.observable(c.Timestamp);”因此生成的 Observable 返回一个 javascript 日期对象(IE 解析问题有时会返回“NaN”)。所以我定义它“this.Timestamp = ko.observable(moment(c.Timestamp));”它返回一个时刻对象。所以我使用了 wdosanjos 在下面指出的排序功能(将此添加到我的问题中)。

标签: javascript arrays knockout.js momentjs


【解决方案1】:

鉴于 .Timestamp 是一个时刻,您应该使用 .isBefore() 和 .isSame() 比较方法,如下所示:

this.Comments.sort(function (left, right) {
    return left.Timestamp.isSame(right.Timestamp) ? 0 : (left.Timestamp.isBefore(right.Timestamp) ? -1 : 1);
});

【讨论】:

  • 感谢您的建议,但不知道。不幸的是,它没有帮助。数组仍然以 n IE9 的相反方式排序。我检查了它,因为文章还具有“firstComment = model.Comments()[0];”的 Knockout 计算字段和“lastComment = model.Comments()[model.Comments().length - 1];”在不同的浏览器中,这两者正好相反。我必须使用浏览器检测来解决这个问题吗???
  • 我发现了这个问题 (stackoverflow.com/a/7501593/2711582),这应该可以解释为什么 IE9 中的排序顺序不同。但不幸的是,它没有提供解决方案。
  • 这是一个可能的解释,因为我的 REST 服务提供已在 JSON 中排序的 cmets,而 IE 只是不排序任何内容。没想到,我看看能不能通过修改sort函数让IE对它进行排序。
  • 好的,我试了一下,observableArray() 提供的敲除 sort() 实现似乎有一个错误。现在,在将元素推送到 observableArray 之前,我已经对 JSON 对象传递的纯 JavaScript 数组进行了排序。功能是相同的,现在一切正常。我正在使用淘汰赛 2.2.1。在我的问题中指出,我的解决方案代码看起来像 EDIT 2。感谢您的提示!
猜你喜欢
  • 2016-10-12
  • 1970-01-01
  • 1970-01-01
  • 2012-05-28
  • 2011-03-25
  • 2013-06-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多