JS实现面包屑导航功能从零开始示例

 更新时间:2023年12月21日 16:25:13   作者:寒露  
这篇文章主要为大家介绍了JS实现面包屑导航功能从零开始示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

面包屑导航

url:domain/path/[[…path]]

目前可以通过 url 的的结构信息定位当前目录的情况,但是无法快速的前进与后退。所以使用“面包屑”来完成这一功能

功能实现

安装依赖

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

鼠标 hover 某个路径时,下拉出现当前路径下文件夹菜单,方便快速跳转。

当菜单超出最大高度时滚动显示。会高亮当前路径上的文件。使用 dom 的 scrollIntoView 方法,确保高亮的菜单在可视区域内。

显示时对菜单项进行 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

对路径进行操作 hooks 文件,对路径字符串项 encodeURIComponent 处理

export const pathExp = /(^\/)?path/
export const encodePathItem = (path: string) => {
  return path
    .split('/')
    .map((text) => encodeURIComponent(text))
    .join('/')
}

效果

git-repo

yangWs29/share-explorer

以上就是JS实现面包屑导航功能从零开始示例的详细内容,更多关于JS面包屑导航的资料请关注脚本之家其它相关文章!

相关文章

  • JavaScript地理位置信息API

    JavaScript地理位置信息API

    这篇文章主要介绍了JavaScript地理位置信息API的相关资料,需要的朋友可以参考下
    2016-06-06
  • 微信小程序实现锚点跳转

    微信小程序实现锚点跳转

    这篇文章主要为大家详细介绍了微信小程序实现锚点跳转,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11
  • 对于JavaScript继承你到底了解多少

    对于JavaScript继承你到底了解多少

    js的继承机制不同于传统的面向对象语言,采用原型链实现继承,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法,下面这篇文章主要给大家介绍了关于JS继承的相关资料,需要的朋友可以参考下
    2021-09-09
  • Javascript闭包(Closure)详解

    Javascript闭包(Closure)详解

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。
    2015-05-05
  • Document:getElementsByName()使用方法及示例

    Document:getElementsByName()使用方法及示例

    Document:getElementsByName()想必大家对它并不陌生吧,主要是根据名称获取元素,下面是其具体的使用方法及范例,感兴趣的朋友不要错过
    2013-10-10
  • JavaScript仿京东放大镜效果

    JavaScript仿京东放大镜效果

    这篇文章主要为大家详细介绍了JavaScript仿京东放大镜效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • js实现文字向上轮播功能

    js实现文字向上轮播功能

    本文主要分享了javascript实现向上文字轮播功能的示例代码。具有一定的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • JavaScript中交换值的10种方法总结

    JavaScript中交换值的10种方法总结

    这篇文章主要给大家总结介绍了JavaScript中交换值的10种方法,文中通过示例代码介绍的非常详细,对大家的学习或者使用JavaScript具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-08-08
  • uniapp自定义验证码输入框并隐藏光标

    uniapp自定义验证码输入框并隐藏光标

    这篇文章主要介绍了uniapp自定义验证码输入框隐藏光标,效果是点击输入框唤起键盘,蓝框就相当于input的光标,验证码输入错误或者不符合格式要求会将字体以及边框改成红色提示持续1s然后清空数据,恢复原边框样式,需要的朋友可以参考下
    2023-02-02
  • JavaScript对象之深度克隆介绍

    JavaScript对象之深度克隆介绍

    这篇文章主要介绍了JavaScript对象之深度克隆介绍,本文详细的讲解了什么是对象深度克隆,并给出了示例代码,需要的朋友可以参考下
    2014-12-12

最新评论