Vue3面包屑(Breadcrumb)

本文介绍了一个Vue3面包屑(Breadcrumb)组件的实现方式,该组件支持多种自定义设置,如路由数组、面包屑样式、分隔符等,并展示了不同场景下的应用实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Vue2面包屑(Breadcrumb)

可自定义设置以下属性:

  • router 的路由数组(routes),类型:Array<{name: string, path?: string, query?: { [propName: string]: any } }>,默认 []

  • 设置面包屑类名(breadcrumbClass),类型:string,默认 undefined

  • 设置面包屑样式(breadcrumbStyle),类型:CSSProperties,默认 {}

  • 设置文本最大显示宽度,超出后显示省略号(maxWidth),类型:string | number,单位 px,默认 '100%'

  • 自定义分隔符(separator),类型:string | slot,默认 undefined,默认使用 '>' 分隔

  • 设置分隔符样式(separatorStyle),类型:CSSProperties,默认 {}

  • 如何打开目标URL,当前窗口或新窗口(target),类型:'_self' | '_blank',默认 '_self'

效果如下图:

在线预览

 ①创建面包屑组件Breadcrumb.vue:

<script setup lang="ts">
import { computed } from 'vue'
import type { CSSProperties } from 'vue'
export interface Query {
  [propName: string]: any // 添加一个字符串索引签名,用于包含带有任意数量的其他属性
}
export interface Route {
  name: string // 路由名称
  path?: string // 路由地址
  query?: Query // 路由查询参数
}
export interface Props {
  routes?: Route[] // router 路由数组
  breadcrumbClass?: string // 设置面包屑类名
  breadcrumbStyle?: CSSProperties // 设置面包屑样式
  maxWidth?: string | number // 设置文本最大显示宽度,超出后显示省略号,单位 px
  separator?: string // 自定义分隔符,默认为 '>' string | slot
  separatorStyle?: CSSProperties // 设置分隔符样式
  target?: '_self' | '_blank' // 如何打开目标 URL,当前窗口或新窗口
}
const props = withDefaults(defineProps<Props>(), {
  routes: () => [],
  breadcrumbClass: undefined,
  breadcrumbStyle: () => ({}),
  maxWidth: '100%',
  separator: undefined,
  separatorStyle: () => ({}),
  target: '_self'
})
const breadcrumbAmount = computed(() => {
  return props.routes.length
})
function getTargetUrl(route: Route): string {
  let targetUrl: string = ''
  if (route.path) {
    targetUrl = route.path
  }
  if (route.query && JSON.stringify(route.query) !== '{}') {
    const query = route.query
    Object.keys(query).forEach((param, index) => {
      if (index === 0) {
        targetUrl = targetUrl + '?' + param + '=' + query[param]
      } else {
        targetUrl = targetUrl + '&' + param + '=' + query[param]
      }
    })
  }
  return targetUrl
}
</script>
<template>
  <div
    class="m-breadcrumb"
    :class="breadcrumbClass"
    :style="[
      `
        --breadcrumb-color: rgba(0, 0, 0, 0.45);
        --breadcrumb-bg-color-hover: rgba(0, 0, 0, 0.06);
        --breadcrumb-color-hover: rgba(0, 0, 0, 0.88);
        --breadcrumb-color-active: rgba(0, 0, 0, 0.88);
        --breadcrumb-padding: 0 4px;
        --breadcrumb-border-radius: 4px;
        --breadcrumb-separator-color: rgba(0, 0, 0, 0.45);
      `,
      breadcrumbStyle
    ]"
  >
    <div class="breadcrumb-item" v-for="(route, index) in routes" :key="index">
      <component
        :is="route.path ? 'a' : 'span'"
        class="breadcrumb-link"
        :class="{
          'link-hover': route.path,
          'link-active': index === breadcrumbAmount - 1
        }"
        :style="`max-width: ${maxWidth}px;`"
        :href="getTargetUrl(route)"
        :target="target"
        :title="route.name"
      >
        {{ route.name }}
      </component>
      <span v-if="index < breadcrumbAmount - 1" class="breadcrumb-separator" :style="separatorStyle">
        <slot name="separator" :route="route" :index="index">
          <span v-if="separator">{{ separator }}</span>
          <svg
            v-else
            focusable="false"
            data-icon="right"
            width="1em"
            height="1em"
            fill="currentColor"
            aria-hidden="true"
            viewBox="64 64 896 896"
          >
            <path
              d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
            ></path>
          </svg>
        </slot>
      </span>
    </div>
  </div>
</template>
<style lang="less" scoped>
.m-breadcrumb {
  font-size: 14px;
  color: var(--breadcrumb-color);
  line-height: 1.5714285714285714;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  .breadcrumb-item {
    display: inline-flex;
    align-items: center;
    .breadcrumb-link {
      display: inline-block;
      color: var(--breadcrumb-color);
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      padding: var(--breadcrumb-padding);
      border-radius: var(--breadcrumb-border-radius);
      text-decoration: none;
      cursor: text;
      transition:
        color 0.2s,
        background-color 0.2s;
    }
    .link-hover {
      cursor: pointer;
      &:hover {
        background-color: var(--breadcrumb-bg-color-hover);
        color: var(--breadcrumb-color-hover);
      }
    }
    .link-active {
      color: var(--breadcrumb-color-active);
    }
    .breadcrumb-separator {
      display: inline-flex;
      align-items: center;
      margin: 0 4px;
      color: var(--breadcrumb-separator-color);
      :deep(svg) {
        margin-left: -2px;
        margin-right: -2px;
        fill: currentColor;
      }
    }
  }
}
</style>

 ②在要使用的页面引入:

其中引入使用了以下组件:

<script setup lang="ts">
import Breadcrumb from './Breadcrumb.vue'
import { ref } from 'vue'
import { ArrowRightOutlined, DoubleRightOutlined } from '@ant-design/icons-vue'
import type { BreadcrumbRoute } from 'vue-amazing-ui'
const routes = ref<BreadcrumbRoute[]>([
  {
    name: '一级路由',
    path: '/first'
  },
  {
    name: '二级路由',
    path: '/second',
    query: { id: 1, tab: 2 }
  },
  {
    name: '三级路由'
  }
])
const longNameRoutes = ref<BreadcrumbRoute[]>([
  {
    name: '一级路由'
  },
  {
    name: '二级路由',
    path: '/second',
    query: { id: 1, tab: 2 }
  },
  {
    name: '我是一个名字超长的三级路由'
  }
])
const customStyle = {
  '--breadcrumb-color': 'rgba(0, 0, 0, 0.65)',
  '--breadcrumb-bg-color-hover': 'rgba(0, 0, 0, 0.1)',
  '--breadcrumb-color-hover': '#ff6900',
  '--breadcrumb-color-active': '#ff6900',
  '--breadcrumb-padding': '4px 8px',
  '--breadcrumb-border-radius': '8px',
  '--breadcrumb-separator-color': 'rgba(0, 0, 0, 0.65)'
}
</script>
<template>
  <div>
    <h1>{{ $route.name }} {{ $route.meta.title }}</h1>
    <h2 class="mt30 mb10">基本使用</h2>
    <Breadcrumb :routes="routes" />
    <h2 class="mt30 mb10">自定义分隔符</h2>
    <Flex vertical>
      <Breadcrumb :routes="routes" separator="/" />
      <Breadcrumb :routes="routes">
        <template #separator>
          <ArrowRightOutlined />
        </template>
      </Breadcrumb>
      <Breadcrumb :routes="routes">
        <template #separator>
          <DoubleRightOutlined />
        </template>
      </Breadcrumb>
    </Flex>
    <h2 class="mt30 mb10">自定义样式</h2>
    <Flex vertical>
      <Breadcrumb
        :routes="longNameRoutes"
        breadcrumb-class="custom-breadcrumb-class"
        :max-width="210"
        :style="customStyle"
      />
      <Breadcrumb
        :routes="longNameRoutes"
        :max-width="210"
        :breadcrumb-style="{ fontSize: '20px' }"
        :style="customStyle"
      />
      <Breadcrumb
        :routes="longNameRoutes"
        :breadcrumb-style="{ fontSize: '20px', height: '40px' }"
        :separator-style="{ fontSize: '18px' }"
        :max-width="210"
      />
      <Breadcrumb
        :routes="longNameRoutes"
        :breadcrumb-style="{ fontSize: '20px', height: '40px' }"
        :separator-style="{ fontSize: '18px' }"
        :max-width="210"
      >
        <template #separator>
          <ArrowRightOutlined />
        </template>
      </Breadcrumb>
      <Breadcrumb
        :routes="longNameRoutes"
        :breadcrumb-style="{ fontSize: '20px', height: '40px' }"
        :separator-style="{ fontSize: '18px' }"
        :max-width="210"
      >
        <template #separator="{ index }">
          <ArrowRightOutlined v-if="index === 0" />
          <DoubleRightOutlined v-if="index === 1" />
        </template>
      </Breadcrumb>
    </Flex>
    <h2 class="mt30 mb10">新页面打开目标链接</h2>
    <Breadcrumb :routes="routes" target="_blank" />
  </div>
</template>
<style lang="less" scoped>
.custom-breadcrumb-class {
  font-size: 20px;
  color: #1677ff;
  height: 40px;
  :deep(.breadcrumb-item) {
    .breadcrumb-link {
      color: rgba(22, 119, 255, 0.72);
      padding: 0 8px;
      border-radius: 8px;
    }
    .link-hover {
      &:hover {
        color: #fff;
        background: #4096ff;
      }
    }
    .link-active {
      color: #1677ff;
    }
    .breadcrumb-separator {
      color: rgba(22, 119, 255, 0.72);
    }
  }
}
</style>
### 使用 Element Plus 在 Vue 3 中实现面包屑组件 为了在 Vue 3 项目中使用 Element Plus 的 `el-breadcrumb` 组件来创建面包屑导航,可以按照如下方式构建: #### HTML 结构 定义模板部分,在其中加入用于显示分隔符图标的图标组件以及具体的面包屑项。 ```html <template> <!-- 静态左侧 --> <el-icon style="margin-right: 10px"> <Expand></Expand> </el-icon> <!-- 动态面包屑 --> <el-breadcrumb separator-icon="ArrowRight"> <el-breadcrumb-item>权限管理</el-breadcrumb-item> <el-breadcrumb-item>用户管理</el-breadcrumb-item> </el-breadcrumb> </template> ``` 此结构展示了两个级别的导航路径:“权限管理” 和 “用户管理”,并且通过箭头图标作为各级之间的分隔符[^2]。 #### 脚本逻辑 对于脚本部分,如果不需要额外处理,则保持默认即可;如果有特定需求比如动态加载菜单数据或响应路由变化等操作,则需在此处编写相应业务逻辑代码。当前示例仅展示基础用法,因此脚本区可为空白状态。 ```typescript <script setup lang="ts"></script> ``` #### 样式定制 最后是样式的定义区域,这里可以根据实际页面布局调整样式属性,使面包屑更好地融入整体设计之中。不过在这个例子里面并没有特别指定任何样式规则,所以这部分也可以留空。 ```scss <style lang="scss" scoped></style> ``` 上述方法能够帮助快速搭建起基于 Element Plus 的简单而有效的面包屑导航栏,适用于大多数场景下的层级化信息指引需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

theMuseCatcher

您的支持是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值