JS 中建立自定義排序方法

爲了保證的可讀性,本文采用意譯而非直譯。前端

想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等着你!git

通常狀況我們排序大都按數字或字母順序,但也有一些狀況下,我們可能須要自定義排序順序。github

在此以前先簡單介紹一下 reduce 方法:數組

語法:arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])函數

callback:執行數組中每一個值的函數,包含四個參數:工具

accumulator:累計器累計回調的返回值; 它是上一次調用回調時返回的累積值,或initialValue(見於下方)。學習

currentValue:數組中正在處理的元素。spa

currentIndex (可選):數組中正在處理的當前元素的索引。 若是提供了initialValue,則起始索引號爲0,不然爲1debug

array(可選): 調用 reduce() 的數組調試

initialValue(可選):做爲第一次調用 callback 函數時的第一個參數的值。 若是沒有提供初始值,則將使用數組中的第一個元素。 在沒有初始值的空數組上調用 reduce 將報錯。

rudeuce 過程描述:

回調函數第一次執行時,accumulatorcurrentValue的取值有兩種狀況:若是調用reduce()時提供了initialValueaccumulator取值爲initialValuecurrentValue取數組中的第一個值;若是沒有提供 initialValue,那麼accumulator取數組中的第一個值,currentValue取數組中的第二個值。

回到原文:

以下面的例子所示,我們想讓 inProgress 在第一位,接着是 todo,而後是 done

const tasks = [
  {id:1, title: 'Job A', status: 'done'},
  {id:2, title: 'Job B', status: 'inProgress'},
  {id:3, title: 'Job C', status: 'todo'},
  {id:4, title: 'Job D', status: 'inProgress'},
  {id:5, title: 'Job E', status: 'todo'}
]

首先按照所需的排序順序建立一個數組。

const sortBy = ['inProgress', 'todo', 'done']

使用reduce來建立一個函數,參數爲一個數組,最後輸出以數組項爲鍵,索引爲值,如 {inProgress:0,todo:1,done:2}

const sortByObject = data => data.reduce(
  (obj,item,index) => ({
    ...obj,
    [item]:index
}), {}
)
console.log(sortByObject(sortBy))
/* {inProgress: 0, todo: 1, done: 2} */

這樣就有了排序設置,我們能夠將它與一個可重用的函數放在一塊兒,該函數傳入一個數組(data)、一個sortby數組和一個sortField,這樣我們就知道要在哪一個字段上排序:

const customSort = ({data, sortBy, sortField}) => {
  const sortByObject = sortBy.reduce(
  (obj, item, index) => ({
      ...obj,
      [item]: index
  }), {})
  return data.sort((a, b) => sortByObject[a[sortField]] - sortByObject[b[sortField]])
}

console.log(customSort({data:tasks, sortBy, sortField: 'status'}))

這樣就能夠按照我們的自定義順序排序,不過還有一個問題,若是列表中有一個status不一樣的項(不在我們的排序順序中),就會出現問題。所以,爲了處理這個問題,我們須要設置一個默認的sort字段來捕獲排序中不須要的全部項。

const tasksWithDefault = tasks.map(item => (
  {  
    ...item,
    sortStatus: sortBy.includes(item.status) ? item.status:'other'
  })
 )

此次傳遞的是更新後的sort字段,那麼如今就有了正確的排序順序,列表底部還有包含狀態爲 other 的項目。

完整代碼:

const tasks = [
  { id: 1, title: "Job A", status: "done" },
  { id: 2, title: "Job B", status: "inProgress" },
  { id: 3, title: "Job C", status: "todo" },
  { id: 3, title: "Job D", status: "onHold" },
  { id: 4, title: "Job E", status: "inProgress" },
  { id: 5, title: "Job F", status: "todo" }
];

const sortBy = ["inProgress", "todo", "done"];

const customSort = ({ data, sortBy, sortField }) => {
  const sortByObject = sortBy.reduce(
    (obj, item, index) => ({
      ...obj,
      [item]: index
    }),
    {}
  );
  return data.sort(
    (a, b) => sortByObject[a[sortField]] - sortByObject[b[sortField]]
  );
};

const tasksWithDefault = tasks.map(item => ({
  ...item,
  sortStatus: sortBy.includes(item.status) ? item.status : "other"
}));
console.log(
  customSort({
    data: tasksWithDefault,
    sortBy: [...sortBy, "other"],
    sortField: "sortStatus"
  })
);

運行結果:

clipboard.png

代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug

原文:https://www.youtube.com/watch...

交流

乾貨系列文章彙總以下,以爲不錯點個Star,歡迎 加羣 互相學習。

https://github.com/qq44924588...

我是小智,公衆號「大遷世界」做者,對前端技術保持學習愛好者。我會常常分享本身所學所看的乾貨,在進階的路上,共勉!

關注公衆號,後臺回覆福利,便可看到福利,你懂的。

clipboard.png

相關文章
相關標籤/搜索