【发布时间】: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