簡體   English   中英

AngularJS orderBy-Chromium瀏覽器中的瘋狂Array.prototype.sort行為-無法清除排序

[英]AngularJS orderBy - crazy Array.prototype.sort behaviour in Chromium browsers - Cannot clear sort

在我的一個項目中,有些事使我發瘋。

我有一些與此非常相似的代碼(我嘗試使其與我的盡可能相似,包括我使用的所有JS文件,等等,但是正如您所見,此Plnkr中的代碼似乎並不重要,因為我無法在此處復制它...): http : //plnkr.co/edit/SCUCsxLgu2zFzMhZ0whs?p=preview

我的問題是,當我設置predicate='' ,排序沒有100%清除。 Angular似乎改變了我的元素順序(此圖片帶有predicate='' ):

在此處輸入圖片說明

當我刪除orderBy ,一切都按其順序排列(就像它是從我的存儲庫中存儲的一樣)。 在使用orderBy嘗試了數百萬種不同的東西之后,我無法完全弄清排序。

我發現這個案例與我的案例有一些相似之處: Chrome中的AngularJS ngRepeat orderBy ,但事實證明我的案例與該問題無關。

我是一個有耐心的人,所以我進入了angular.js文件(AngularJS v1.3.15)並開始調試。 這是最關鍵的行:

return slice.call(array).sort(reverseComparator(comparator, reverseOrder));

直到slice.call(array)排列良好。 執行sort時,結果是錯誤的。 所以我這樣做:

function comparator(o1, o2) {
  for (var i = 0; i < sortPredicate.length; i++) {
    var comp = sortPredicate[i](o1, o2);
    if (comp !== 0){
      console.log(7);  // <---------------------
      return comp;
    }
  }
  console.log(0);      // <---------------------
  return 0;
}

function reverseComparator(comp, descending) {
  return descending
      ? function(a, b) {return comp(b,a);}
      : comp;
}

猜猜是什么:當predicate=''為零時,我在控制台中得到的所有內容。 另外,輸入:

slice.call(array).sort

...的回報:

function sort() { [native code] }

因此,我不知道為什么要進行這種排序。 看來,這僅發生在基於Chromium的瀏覽器中(我嘗試過Chrome和Opera)。 FF和IE11按預期清除了排序。

現在,我認為這是一個Chromium錯誤,但是我仍然沒有設法在那個Plnkr中重現它,我想知道為什么(也許數據有些不同?)...

我也嘗試過禁用Chrome擴展程序,但這似乎也沒有什么不同。

鉻和Angular現已聞名。 有人之前注意到過嗎?

有人知道這是怎么回事嗎?

更新:

好。 我想我已經通過在數組中添加更多項來重現它。 看到這里: http : //plnkr.co/edit/SCUCsxLgu2zFzMhZ0whs?p=preview

(聚會時間!:D)

我要去報告給Angular團隊。 他們是Google。 他們也可能會修復Chromium。 :d

來自ECMAScript規范

排序不一定是穩定的(也就是說,比較相等的元素不一定保持其原始順序)。

因此,這不是瀏覽器中的錯誤。

Angular代碼確實考慮了一個空謂詞:

if (predicate === '') {
  // Effectively no predicate was passed so we compare identity
  return reverseComparator(compare, descending);
}

具有compare功能

function compare(v1, v2) {
  var t1 = typeof v1;
  var t2 = typeof v2;
  if (t1 === t2 && t1 === "object") {
    v1 = objectToString(v1);
    v2 = objectToString(v2);
  }
  ...

objectToString

function objectToString(value) {
  if (value === null) return 'null';
  if (typeof value.valueOf === 'function') {
    value = value.valueOf();
    if (isPrimitive(value)) return value;
  }
  if (typeof value.toString === 'function') {
    value = value.toString();
    if (isPrimitive(value)) return value;
  }
  return '';
}

由於您的對象都沒有自己 valueOf方法或toString方法,因此它們最終是相等的(該函數可能會返回"[object Object]" )。 這使我們回到了ECMAScript規范。

我最終將采用的解決方案是使用以下自定義過濾器:

(function () {

    function isNullOrEmpty(str) {
        return str === '' || str === undefined || str === null;
    }

    angular.module('CustomFilters', [])
        .filter('okOrderBy', ['$filter', function ($filter) {

            return function (array, predicate, reverse) {
                if (isNullOrEmpty(predicate)) return array;
                return $filter('orderBy')(array, predicate, reverse);
            };
        }
        ])
        .filter('arrayOrderBy', [function () {

            function Comparator(predicate, reverse) {
                return reverse ? function (a, b) {
                    a = a[predicate];
                    b = b[predicate];
                    if (a === b) return 0;
                    return a < b ? 1 : -1;
                } : function (a, b) {
                    a = a[predicate];
                    b = b[predicate];
                    if (a === b) return 0;
                    return a < b ? -1 : 1;
                };
            }

            return function (array, predicate, reverse) {
                if (isNullOrEmpty(predicate)) return array;
                return array.slice(0).sort(new Comparator(predicate, reverse));
            };
        }
        ]);

})();

第二個獨立於Angular濾鏡,我更喜歡它。

但是它僅適用於對象數組,其謂詞僅是屬性名稱,並且不允許“多列”排序。 雖然第一個應該對所有東西都起作用(我想)。

我在應該接受的答案上有一個很大的難題,因為所有其他答案都是有益和有趣的。 我希望我可以不勝感激地投票給他們一次以上。 我正在考慮選擇此答案(我知道...我很自私...),只是因為它解決了問題,並且比用戶“ YOU”提供的答案使用時間短。

另一種方法。 不需要時不要運行排序。

高興的角度讓您可以在此處編寫任何內容。

<tr ng-repeat="friend in (predicate ? (friends | orderBy:predicate:reverse) : friends)">
  <td>{{friend.name}}</td>
  <td>{{friend.phone}}</td>
  <td>{{friend.age}}</td>
</tr>

http://plnkr.co/edit/KIdAKPtA3JDtRMDD50VI?p=preview

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM