从零开始-文件资源管理器-20-文件呈现排序

JavaScript 的 array sort 方法对字符串的排序有些问题。

纯数字

[1, 2, 3, 11].sort()
=> [1, 11, 2, 3]

字符串

['a', 'e', 'b', 'c', 'd'].sort()
=> ['a', 'b', 'c', 'd', 'e']

数字加字符串

['a-1', 'a-2', 'a-2', 'a-11'].sort()
=> ['a-1', 'a-11', 'a-2', 'a-3']

上面的例子发现,字符串的可以排序正常,数字的 11 会拍在 2 的前面。纯数字的可以通过 sort((a, b) => a - b) 的回调控制挣钱排序。

如果涉及到"字符串+数字"的时候,简单的 a - b 无法完成排序任务。

这里引用一个自然排序的依赖 natural-compare-lite可以正确处理文件名的排序问题。

开发

explorer

安装依赖

pnpm i natural-compare-lite

pnpm i @types/natural-compare-lite -D

创建 sort 排序 context 组件,并创建四个排序方法

  • 时间的正排序与逆排序
  • 文件名正排序与逆排序

对文件名的排序使用 naturalCompare 依赖方法。

'use client'
import naturalCompare from 'natural-compare-lite'
import { ReaddirItemType } from '@/explorer-manager/src/type'
import createCtx from '@/lib/create-ctx'
import React from 'react'

export type SortAction = (a: ReaddirItemType, b: ReaddirItemType) => number

export const nameAscSort: SortAction = (a, b) => naturalCompare(a.name, b.name)
export const dateAscSort: SortAction = (a, b) => (a?.stat?.mtimeMs || 0) - (b?.stat?.mtimeMs || 0)
export const nameDescSort: SortAction = (a, b) => naturalCompare(b.name, a.name)
export const dateDescSort: SortAction = (a, b) => (b?.stat?.mtimeMs || 0) - (a?.stat?.mtimeMs || 0)

export const sortMap = {
  asc_name: nameAscSort,
  asc_date: dateAscSort,
  desc_name: nameDescSort,
  desc_date: dateDescSort,
}

export const SortContext = createCtx<'asc_name' | 'asc_date' | 'desc_name' | 'desc_date'>()

export const useSortStore = SortContext.useStore

export const useSortDispatch = SortContext.useDispatch

export const SortProvider: React.FC<React.PropsWithChildren> = ({ children }) => {
  return <SortContext.ContextProvider value="asc_name">{children}</SortContext.ContextProvider>
}

创建一个控制排序的下拉菜单组件

'use client'
import React from 'react'
import { Button, Dropdown } from 'antd'
import { SortAscendingOutlined, SortDescendingOutlined } from '@ant-design/icons'
import { useSortDispatch, useSortStore } from '@/components/readdir-sort/sort-context'

const ReaddirSort: React.FC = () => {
  const sort = useSortStore()
  const sortDispatch = useSortDispatch()

  return (
    <Dropdown
      placement="top"
      arrow={true}
      trigger={['hover', 'click']}
      menu={{
        selectedKeys: [sort],
        items: [
          {
            key: 'asc_name',
            icon: <SortAscendingOutlined />,
            onClick: () => {
              sortDispatch('asc_name')
            },
            label: '名称正排',
          },
          {
            key: 'desc_name',
            icon: <SortDescendingOutlined />,
            onClick: () => {
              sortDispatch('desc_name')
            },
            label: '名称倒排',
          },
          {
            key: 'asc_date',
            icon: <SortAscendingOutlined />,
            onClick: () => {
              sortDispatch('asc_date')
            },
            label: '时间正排',
          },
          {
            key: 'desc_date',
            icon: <SortDescendingOutlined />,
            onClick: () => {
              sortDispatch('desc_date')
            },
            label: '时间倒排',
          },
        ],
      }}
    >
      <Button icon={<SortAscendingOutlined />} />
    </Dropdown>
  )
}

export default ReaddirSort

为 readdir-context 内的 useReaddirContext 读取 sort 属性对 readdir_list 进行 sort 排序

export const useReaddirContext = () => {
  const readdir_list = ReaddirContext.useStore()
  const sort = useSortStore()

  return readdir_list.sort(sortMap[sort])
}

为保证能正确读取到 useSortStore 属性。需要将 SortProvider 插入 ReaddirProvider 上下文组件之前。

...

export const PathContextProvider: React.FC<React.ProviderProps<ReaddirListType>> = ({ value, children }) => {
  return (
    <SortProvider>
      <ReaddirProvider value={value}>
        ...
                        <VideoInfoProvider>{children}</VideoInfoProvider>
        ...
      </ReaddirProvider>
    </SortProvider>
  )
}

到此,对文件排序功能完成

效果

截屏2023-12-24 10.51.36.png

git-repo

yangWs29/share-explorer

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,607评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,239评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,960评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,750评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,764评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,604评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,347评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,253评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,702评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,893评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,015评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,734评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,352评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,934评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,052评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,216评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,969评论 2 355

推荐阅读更多精彩内容