原文:www.youtube.com/watch?v=zVe…html
譯者:前端小智前端
阿里雲最近在作活動,低至2折,有興趣能夠看看:promotion.aliyun.com/ntms/yunpar…git
爲了保證的可讀性,本文采用意譯而非直譯。github
通常狀況我們排序大都按數字或字母順序,但也有一些狀況下,我們可能須要自定義排序順序。數組
在此以前先簡單介紹一下 reduce
方法:函數
語法:arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
工具
callback:執行數組中每一個值的函數,包含四個參數:學習
accumulator:累計器累計回調的返回值; 它是上一次調用回調時返回的累積值,或initialValue
(見於下方)。阿里雲
currentValue:數組中正在處理的元素。spa
currentIndex (可選):數組中正在處理的當前元素的索引。 若是提供了initialValue
,則起始索引號爲0
,不然爲1
。
array(可選): 調用 reduce()
的數組
initialValue(可選):做爲第一次調用 callback
函數時的第一個參數的值。 若是沒有提供初始值,則將使用數組中的第一個元素。 在沒有初始值的空數組上調用 reduce
將報錯。
rudeuce 過程描述:
回調函數第一次執行時,accumulator
和currentValue
的取值有兩種狀況:若是調用reduce()
時提供了initialValue
,accumulator
取值爲initialValue
,currentValue
取數組中的第一個值;若是沒有提供 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"
})
);
複製代碼
運行結果:
代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug。
乾貨系列文章彙總以下,以爲不錯點個Star,歡迎 加羣 互相學習。
我是小智,公衆號「大遷世界」做者,對前端技術保持學習愛好者。我會常常分享本身所學所看的乾貨,在進階的路上,共勉!
關注公衆號,後臺回覆福利,便可看到福利,你懂的。