JS實(shí)現(xiàn)面包屑導(dǎo)航功能從零開始示例
面包屑導(dǎo)航
url:domain/path/[[…path]]
目前可以通過 url 的的結(jié)構(gòu)信息定位當(dāng)前目錄的情況,但是無法快速的前進(jìn)與后退。所以使用“面包屑”來完成這一功能
功能實(shí)現(xiàn)
安裝依賴
cd /explorer pnpm i axios ahooks
文件樹
explorer/src/app/path/[[...path]]/layout.tsx
explorer/src/app/path/api/readdir/route.ts
explorer/src/components/breadcrumb-dropdown-readdir/index.tsx
explorer/src/components/explorer-breadcrumb/index.tsx
explorer/src/components/use-replace-pathname.ts
文件路徑:explorer/src/app/path/api/readdir/route.ts
新增一個獲取指定目錄的接口
import { NextRequest, NextResponse } from 'next/server'
import { readdir } from '@/explorer-manager/src/main.mjs'
export type SearchParamsType = {
path: string
only_dir: '0' | '1'
only_file: '0' | '1'
has_file_stat: '0' | '1'
}
export const GET = async (req: NextRequest) => {
const { path, only_dir, only_file, has_file_stat } = Object.fromEntries(req.nextUrl.searchParams) as SearchParamsType
return NextResponse.json({ readdir: readdir(path, { only_dir, only_file, has_file_stat }) })
}文件路徑:explorer/src/app/path/[[...path]]/layout.tsx
將面包屑組件添加至 layout 的 Card 組件 title 部分。
import React from 'react'
import { readdir } from '@/explorer-manager/src/main.mjs'
import { PathContextProvider } from '@/app/path/context'
import { Card } from 'antd'
import ExplorerBreadcrumb from '@/components/explorer-breadcrumb'
const Layout: React.FC<React.PropsWithChildren & { params: { path: string[] } }> = ({
children,
params: { path = [] },
}) => {
const readdirList = readdir(path.join('/'), { only_dir: '0', only_file: '0', has_file_stat: '1' })
return (
<PathContextProvider value={readdirList}>
<Card title={<ExplorerBreadcrumb />}>{children}</Card>
</PathContextProvider>
)
}
export default Layout文件路徑:explorer/src/components/explorer-breadcrumb/index.tsx
面包屑組件,使用 Antd 的 Breadcrumb 組件。跟目錄"/"使用 home icon 替代
'use client'
import React from 'react'
import Link from 'next/link'
import { HomeOutlined } from '@ant-design/icons'
import { usePathname } from 'next/navigation'
import { Breadcrumb, Space } from 'antd'
import BreadcrumbDropdownReaddir from '@/components/breadcrumb-dropdown-readdir'
type ItemType = { title: string; href: string }
const ExplorerBreadcrumb: React.FC = () => {
const pathname = usePathname() || ''
return (
<Space>
<Breadcrumb
items={decodeURIComponent(pathname)
.split('/')
.filter(Boolean)
.reduce<ItemType[]>((p, c) => {
const last = p[p.length - 1]
return p.concat({ title: c, href: [last?.href, c].join('/') })
}, [])
.map(({ title, href }, k, { length }) => {
return {
title:
length === k + 1 && length !== 1 ? (
title
) : (
<BreadcrumbDropdownReaddir title={title} href={href}>
<Link href={href}>{k === 0 ? <HomeOutlined /> : title}</Link>
</BreadcrumbDropdownReaddir>
),
}
})}
/>
</Space>
)
}
export default ExplorerBreadcrumb文件路徑:explorer/src/components/breadcrumb-dropdown-readdir/index.tsx
鼠標(biāo) hover 某個路徑時,下拉出現(xiàn)當(dāng)前路徑下文件夾菜單,方便快速跳轉(zhuǎn)。
當(dāng)菜單超出最大高度時滾動顯示。會高亮當(dāng)前路徑上的文件。使用 dom 的 scrollIntoView 方法,確保高亮的菜單在可視區(qū)域內(nèi)。
顯示時對菜單項(xiàng)進(jìn)行 decodeURIComponent 處理,保證顯示的文本正確。
import React, { useRef } from 'react'
import { Dropdown, Menu } from 'antd'
import { useMount, useRequest } from 'ahooks'
import axios from 'axios'
import { ReaddirListType } from '@/explorer-manager/src/type'
import { encodePathItem, pathExp } from '@/components/use-replace-pathname'
import Link from 'next/link'
import { FolderOpenOutlined, FolderOutlined } from '@ant-design/icons'
import { usePathname } from 'next/navigation'
const ScrollIntoView: React.FC<{ is_open: boolean; className?: string }> = ({ is_open, className }) => {
const ref = useRef<HTMLDivElement>(null)
useMount(() => {
is_open && ref.current?.scrollIntoView({ block: 'center', behavior: 'instant' })
})
return is_open ? <FolderOpenOutlined ref={ref} className={className} /> : <FolderOutlined className={className} />
}
const BreadcrumbDropdownReaddir: React.FC<React.PropsWithChildren & { title: string; href: string }> = ({
children,
href,
title,
}) => {
const pathname = usePathname() || ''
const { data = [], runAsync } = useRequest(
() =>
axios
.get<{ readdir: ReaddirListType }>('/path/api/readdir', {
params: { path: href.replace(pathExp, ''), only_dir: 1 },
})
.then(({ data: { readdir } }) => {
return readdir
}),
{ manual: true, cacheKey: `readdir-${href}`, staleTime: 60 * 1000 },
)
const open_dit_text =
decodeURIComponent(pathname).split([title, '/'].join('')).pop()?.split('/').filter(Boolean).shift() || ''
return (
<Dropdown
destroyPopupOnHide={true}
arrow={true}
trigger={['hover']}
dropdownRender={() => {
return (
<Menu
selectedKeys={[open_dit_text]}
style={{ maxHeight: '50vw', overflow: 'scroll' }}
items={data?.map((item) => {
const is_open = open_dit_text === item.name
return {
label: (
<Link href={encodePathItem(`${href}/${item.name}`)} prefetch={false}>
{item.name}
</Link>
),
key: item.name,
icon: <ScrollIntoView is_open={is_open} />,
}
})}
/>
)
}}
onOpenChange={(open) => {
open && runAsync().then()
}}
>
{children}
</Dropdown>
)
}
export default BreadcrumbDropdownReaddir文件路徑:explorer/src/components/use-replace-pathname.ts
對路徑進(jìn)行操作 hooks 文件,對路徑字符串項(xiàng) encodeURIComponent 處理
export const pathExp = /(^\/)?path/
export const encodePathItem = (path: string) => {
return path
.split('/')
.map((text) => encodeURIComponent(text))
.join('/')
}效果

git-repo
以上就是JS實(shí)現(xiàn)面包屑導(dǎo)航功能從零開始示例的詳細(xì)內(nèi)容,更多關(guān)于JS面包屑導(dǎo)航的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript實(shí)現(xiàn)生成隨機(jī)密碼的示例詳解
使用JavaScript我們可以輕松地在客戶端生成隨機(jī)密碼,本文我們將實(shí)現(xiàn)一個簡單的隨機(jī)密碼生成器,能夠生成指定長度和包含特定字符集的密碼,有需要的可以參考下2024-01-01
js事件機(jī)制----捕獲與冒泡機(jī)制實(shí)例分析
這篇文章主要介紹了js事件機(jī)制----捕獲與冒泡機(jī)制,結(jié)合實(shí)例形式分析了js事件機(jī)制中捕獲與冒泡機(jī)制相關(guān)原理、操作技巧與注意事項(xiàng),需要的朋友可以參考下2020-05-05
JSON.parse處理非標(biāo)準(zhǔn)Json數(shù)據(jù)出錯的解決
這篇文章主要介紹了JSON.parse處理非標(biāo)準(zhǔn)Json數(shù)據(jù)出錯的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09
基于javascript實(shí)現(xiàn)仿百度輸入框自動匹配功能
這篇文章主要介紹了基于javascript實(shí)現(xiàn)仿百度輸入框自動匹配功能的相關(guān)資料,需要的朋友可以參考下2016-01-01
javascript replace()正則替換實(shí)現(xiàn)代碼
javascript-replace()基礎(chǔ),一次完成將"<,>"替換"<>"實(shí)例2010-02-02
JavaScript基礎(chǔ)知識之方法匯總結(jié)
本文給大家分享了javascript基礎(chǔ)知識,包括數(shù)組的方法,函數(shù)的方法,數(shù)字的方法,對象的方法,字符串的方法,常規(guī)方法,正則表達(dá)式方法,本文介紹的非常詳細(xì),具有參考價值特此分享供大家參考2016-01-01

