Knockout-IE没有排序可观察数组(Chrome和Firefox确实如此)

时间:2014-02-05 14:25:15

标签: knockout.js single-page-application knockout-2.0 hottowel

我正在使用淘汰赛制作单页应用程序。 对于这个非常奇怪的问题,我一直在撞墙。 IE奇怪地决定不对我的可观察数组进行排序,而Chrome和Firefox确实按预期工作。

这里是代码:tr click事件调用sort函数,但IE根本没有对它进行排序

var lastResponseSort = '';

var sortResponses = function (data, event) {
var sortField = $(event.target).attr("data-arg");

   if (sortField !== undefined) {
   var descending = lastResponseSort != "";
   lastResponseSort == "" ? lastResponseSort = sortField : lastResponseSort = "";

   // Sort Array here
   arrResponses.sort(function (x, y) {
      if (descending) {
      return x[sortField] > y[sortField] ? -1 : 1;
      } else {
       return x[sortField] < y[sortField] ? -1 : 1;
      }
    });
   }

HTML:

   <table id="crisis-info">
   <thead>
     <tr data-bind="click: sortResponses">
        <th data-arg="eventName">Response name</th>
        <th data-arg="eventRelatesCrisisTypes()[0].crisisType().name">Crisis Type</th>
        <th data-arg="numberOfPeopleAffected">Affected</th>
        <th data-arg="country().name">Country &amp; Region</th>
     </tr>
   </thead>
   <tbody data-bind="visible: arrResponses().length > 0, foreach: arrResponses">
       <tr>
        <td><span data-bind="text: eventName(), attr: { title:eventName() }"></span>
        </td>
        <td><span data-bind="text: eventRelatesCrisisTypes()[0].crisisType().name(),attr: { title: eventRelatesCrisisTypes()[0].crisisType().name() }"></span>
        </td>
        <td align="center"><span data-bind="text: numberOfPeopleAffected()"></span>
        </td>
        <td><span data-bind="text: country().name() + ',  ' + country().region().name()"></span></td>
        </tr>
       </tbody>
   </table>

问题的一部分更令人着迷的是,在应用调试器并通过sort函数时,IE甚至不对数组进行排序,更不用说更新我认为是问题的UI,也不会抛出任何错误。如果有人遇到此问题或知道解决方法,请分享。 谢谢

1 个答案:

答案 0 :(得分:1)

由于您尝试动态访问对象的属性和/或子属性,因此您需要使用eval而不是动态属性访问。因此x[sortField]需要eval('x.' + sortField)

此外,由于属性是可观察的,您还需要添加尾随括号:eval('x.' + sortField)()

这是您更新的排序函数(以及其他一些优化):

arrResponses.sort(function (x, y) {
    var xLess = eval('x.' + sortField + '() < y.' + sortField + '()');
    if (descending) {
        return xLess ? 1 : -1;
    } else {
        return xLess ? -1 : 1;
    }
});

另一个我更强烈建议的解决方案是在对象中使用计算的observable来封装显示的数据。因此,您的Response对象将包含以下内容:

this.crisisType = ko.computed(function () {
    return this.eventRelatesCrisisTypes()[0].crisisType().name();    
}, this);

this.countryRegion = ko.computed(function () {
    return this.country().name() + ', ' + this.country().region().name();
}, this);

现在,您可以在视图中绑定这些计算的observable,并在sort函数中使用它们,而无需使用eval