面包屑最简单使用+element+标签

本文章是对element-ui的tab标签进行二次封装,为

无不良引导,使用方便。

封装element-ul的标签(面包屑)

对element里面的tab标签进行二次封装

第一步

在public文件夹下新创建一个组件/public/TabELement.vue

将下列代码粘进

<template>
  <div>
    <div style="text-align: left" class="box_right_Tag">
      <!-- 圆角 -->
      <div class="T" v-if="fixed" style="display: flex">
        <!-- 使用 tag.id 作为唯一的 key -->

        <el-tag
          :size="size"
          style="cursor: pointer"
          :key="index"
          :effect="effect"
          :type="$route.fullPath == tag.fullPath ? `${type}` : 'info'"
          v-for="(tag, index) in dynamicTags"
          :disable-transitions="false"
          @close="HandleClose(tag, index)"
        >
          <router-link :to="tag.fullPath" tag="b"> {{ tag.title }}</router-link>
        </el-tag>
      </div>
      <!-- 删除 -->
      <div class="T" v-else-if="closable" style="display: flex">
        <!-- 使用 tag.id 作为唯一的 key -->
        <el-tag
          closable
          :size="size"
          style="cursor: pointer"
          :key="index"
          :effect="effect"
          :type="$route.fullPath == tag.fullPath ? `${type}` : 'info'"
          v-for="(tag, index) in dynamicTags"
          :disable-transitions="false"
          @close="HandleClose(tag, index)"
        >
          <router-link :to="tag.fullPath" tag="b"> {{ tag.title }}</router-link>
        </el-tag>
      </div>
      <!-- 圆角/删除 -->
      <div class="T" v-else style="display: flex">
        <!-- 使用 tag.id 作为唯一的 key -->

        <el-tag
          :size="size"
          style="cursor: pointer"
          :key="tag.id"
          :effect="effect"
          :type="$route.fullPath == tag.fullPath ? `${type}` : 'info'"
          v-for="(tag, index) in dynamicTags"
          :closable="!(tag.fullPath == `${firstRouter.fullPath}`)"
          :disable-transitions="false"
          @close="HandleClose(tag, index)"
        >
          <router-link :to="tag.fullPath" tag="b"> {{ tag.title }}</router-link>
        </el-tag>
        <!-- 使用 tag.id 作为唯一的 key -->
      </div>
      <div>
        <el-dropdown @command="handleCommand">
          <span class="el-dropdown-link">
            <i
              style="font-size: 20px"
              class="el-icon-arrow-down el-icon--right"
            ></i>
          </span>
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item command="a">关闭全部</el-dropdown-item>
            <el-dropdown-item command="b" divided>关闭其他</el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
      </div>
    </div>
  </div>
</template>
 
<script>
export default {
  props: {
    // 修正 props 类型定义的大小写错误
    interface: {
      type: String,
    },
    NameTitle: {
      type: String,
    },
    size: {
      type: String,
    },
    type: {
      type: String,
    },
    effect: {
      type: String,
    },
    fixed: {
      type: Boolean,
      default: false,
    },
    closable: {
      type: Boolean,
      default: false,
    },
  },
  // 监听器
  // 监听器监听路由变化
  watch: {
    $route: {
      handler(newRoute) {
        // 当 $route 发生变化时执行的逻辑
        this.Cun_Chu_route_fullPath = newRoute.fullPath; // 获取当前的路由接口
        this.Cun_Chu_route_Title = newRoute.meta.title; // 获取当前的路由接口 title
        this.inputValue = {
          title: newRoute.meta.title,
          fullPath: newRoute.fullPath,
          // 生成唯一的 id
          id: Date.now(),
        };
        this.showInput();
        this.HandleInputAdd();
      },
      deep: true, // 开启深度监听
      immediate: true, // 组件加载时立即执行一次 handler
    },
  },
  // 变量
  data() {
    return {
      isAssigned: false, // 标志位,用于记录变量是否已赋值
      firstRouter: {
        fullPath: "",
        TiTle: "",
      }, // 页面加载第一次路由
      Cun_Chu_route_fullPath: "", // 当前页面的路由
      Cun_Chu_route_Title: "", // 当前页面的路由 title
      dynamicTags: [], // 存储的标签内容
      inputVisible: false, // 标签的显示与隐藏
      inputValue: {}, // 标签获取内容
    };
  },
  // 函数
  methods: {
    handleCommand(command) {
      // 地域嵌套
      if (command === "a") {
        this.dynamicTags = [];
        const firstTag = {
          fullPath: this.firstRouter.fullPath,
          title: this.firstRouter.TiTle,
          // 生成唯一的 id
          id: Date.now(),
        };
        this.dynamicTags.push(firstTag);
        this.$router.push(this.firstRouter.fullPath).catch(() => {});
      }
      if (command === "b") {
        let is = this.Cun_Chu_route_fullPath;
        if (is) {
          if (this.Cun_Chu_route_fullPath === this.firstRouter.fullPath) {
            this.dynamicTags = [
              {
                fullPath: this.firstRouter.fullPath,
                title: this.firstRouter.TiTle,
                // 生成唯一的 id
                id: Date.now(),
              },
            ];
          } else {
            this.dynamicTags = [
              {
                fullPath: this.firstRouter.fullPath,
                title: this.firstRouter.TiTle,
                // 生成唯一的 id
                id: Date.now(),
              },
              {
                fullPath: this.Cun_Chu_route_fullPath,
                title: this.Cun_Chu_route_Title,
                // 生成唯一的 id
                id: Date.now(),
              },
            ];
          }
        } else {
          return;
        }
      }
    },
    // 删除标签
    HandleClose(tag, index) {
      console.log(this.dynamicTags);
      if (this.dynamicTags.length === 0) {
        console.log(2);
      }
      // 来判断当前页面的路由和点击删除的路由是否一致
      if (this.Cun_Chu_route_fullPath === this.dynamicTags[index].fullPath) {
        // 点击删除面包屑路由跳转下一个路由,用来判断点击的下标是是否和数组的最后一项是否一致
        if (
          this.dynamicTags[index].fullPath ===
          this.dynamicTags[this.dynamicTags.length - 1].fullPath
        ) {
          if (this.firstRouter.fullPath === undefined) {
            this.firstRouter.fullPath = this.Cun_Chu_route_fullPath;
          }
          console.log(1111);
          console.log(
            `${this.firstRouter.fullPath}`,
            "1111111111111+++++1111111"
          );
          this.$router.push(this.firstRouter.fullPath).catch(() => {});
        } else {
          console.log(
            `${this.dynamicTags[index + 1].fullPath}`,
            "2222222222222222222222222222222"
          );
          this.$router.push(this.dynamicTags[index + 1].fullPath);
        }
      }
      // 删除点击的面包屑
      this.dynamicTags.splice(this.dynamicTags.indexOf(tag), 1);
    },
    // 控制标签显示
    showInput() {
      this.inputVisible = true;
    },
    // 添加标签
    HandleInputAdd() {
      for (let item of this.dynamicTags) {
        if (this.inputValue.title === item.title) return;
      }
      let inputValue = this.inputValue;
      if (inputValue) {
        this.dynamicTags.push(inputValue);
        this.removeDuplicateTags();
      }
      this.inputVisible = false;
    },
    removeDuplicateTags() {
      const uniqueIds = new Set();
      this.dynamicTags = this.dynamicTags.filter((tag) => {
        if (uniqueIds.has(tag.id)) {
          return false;
        }
        uniqueIds.add(tag.id);
        return true;
      });
    },
  },
  // 生命周期
  mounted() {
    if (!this.isAssigned) {
      if (this.NameTitle === undefined) {
        this.firstRouter.fullPath = this.$route.fullPath;
        this.firstRouter.TiTle = this.$route.meta.title;
      } else {
        this.firstRouter.fullPath = this.interface;
        this.firstRouter.TiTle = this.NameTitle;
      }
      this.isAssigned = true; // 标记为已赋值
    }
    this.showInput();
    this.HandleInputAdd();
  },
};
</script>
 
<style lang="scss" scoped>
.box_right_Tag {
  overflow: hidden;
  padding: 10px 30px 10px 10px;
  background: #ffffff;
  border: 1px dotted #409eff;
  display: flex;
  justify-content: space-between;
  align-items: center;
  .T {
    overflow: hidden;
  }
  .el-dropdown-link {
    cursor: pointer;
    color: #409eff;
  }
  .el-icon-arrow-down {
    font-size: 12px;
  }
}

.el-tag + .el-tag {
  margin-left: 10px;
}
.button-new-tag {
  margin-left: 10px;
  height: 32px;
  line-height: 30px;
  padding-top: 0;
  padding-bottom: 0;
}
.input-new-tag {
  width: 90px;
  margin-left: 10px;
  vertical-align: bottom;
}
</style>

第二步

把组件TabELement.vue通过注册组件方式引入

局部引入

<template>
  <div>
  
  
  <TabELement
   size="mini"
   type=" "
   effect="dark"
  ></TabELement>
  
  </div>
</template>

<script>
import TabELement from "../../public/TabELement.vue";

export default {
  components: {
    TabELement,
  },
};
</script>

<style>
</style>

全局引入

main.js中

import Vue from 'vue';
import App from './App.vue';
// 引入要全局注册的组件
import TabELement from "../public/TabELement.vue";

// 全局注册组件
Vue.component('TabELement', TabELement);

new Vue({
  render: h => h(App),
}).$mount('#app');

在页面使用

<template>
  <div>
    <h1>使用全局组件示例</h1>
    <!-- 直接使用全局注册的组件 -->
    <TabELement />
  </div>
</template>

<script>
export default {
  name: 'App'
};
</script>

<style scoped>
/* 样式 */
</style>

第三步

例如:给路由配置标签里面标题

第四步:重新启动终端

第五步参数说明

参数

说明

类型

interface

固定首页地址栏标签或者移除所有标签

string/boolean

当前首页路由地址地址

例如:/home/message

NameTitle

首页地址栏标签标题

string

首页

size

标签大小

string

medium / small /mini/

type

不同颜色

string

success/info/warning/danger

effect

不同形式

string

dark / light / plain

closable

允许删除

本身

closable

 fixed

固定不删除

本身

fixed

  <TabELement effect="dark" closable type="danger"></TabELement>

   <TabELement effect="dark" fixed></TabELement>

<think>好的,我现在需要帮用户了解如何在网页中实现面包屑导航栏。首先,我应该回顾用户提供的系统级指令,确保回答符合格式要求。比如,所有行内数学表达式要用$...$,但这个问题可能用不上数学公式。不过要注意使用中文,生成相关问题,并在引用处加上标识。 用户的问题是关于网页中面包屑导航栏的实现。他们提供的参考引用有三个,分别是关于Element-UI组件、HTML结构和Flutter的实现。但用户现在问的是网页实现,所以可能需要重点看引用1和2。不过引用3是Flutter的,可能不相关,但需要确认是否有用。 首先,我需要整理网页实现面包屑导航的基本方法。可能包括使用HTML和CSS手动构建,或者使用现有的UI框架如Element-UI。根据引用1,Element-UI有现成的组件,可以方便地实现。引用2给出了一个HTML结构的例子,显示了一个列表项的结构,可能使用无序列表和链接。 接下来,我需要分步骤说明如何实现。第一步可能是使用HTML创建结构,用<ul>和<li>元素,结合链接。然后,使用CSS美化,比如添加分隔符(如斜杠或箭头),处理间距,悬停效果等。之后,可以提到使用JavaScript或框架(如Vue.js配合Element-UI)来动态生成面包屑导航,根据当前页面路径更新导航内容。 需要注意引用中的内容,引用1提到面包屑的作用和Element-UI的实现,引用2给出了HTML代码示例,所以需要在回答中引用这两个。而引用3是Flutter的实现,可能用户的问题不涉及移动端,所以可能不需要提及,但如果有相关部分可以适当关联。 用户可能还需要知道如何动态生成导航栏,比如根据路由信息自动生成层级。这时候可能需要使用JavaScript来解析当前URL路径,分割成各个部分,并生成对应的链接。或者,在单页面应用(SPA)中使用前端框架(如React、Vue)来管理路由状态,并动态渲染面包屑。 另外,需要提到SEO友好性和可访问性,比如使用ARIA标签或者结构化数据,但用户提供的引用中没有这方面的信息,可能需要简单提及。 现在,我需要确保回答结构清晰,分步骤说明,并引用提供的参考资料。例如,在讲解Element-UI组件时,引用[^1],在展示HTML结构时引用[^2]。 可能的问题点:如何动态生成路径?是否需要后端参与?是否需要处理嵌套路由? 最后,生成相关问题,如优化方法、不同框架的实现、动态路径处理等。</think>### 如何在网页中实现面包屑导航栏 面包屑导航栏通过层级链接帮助用户理解当前位置并快速跳转。以下是具体实现方法: --- #### 一、基础HTML结构 使用`<ul>`和`<li>`标签构建层级,每个层级对应一个链接: ```html <nav class="breadcrumb"> <ul> <li class="breadcrumb-item"><a href="/">首页</a></li> <li class="breadcrumb-item"><a href="/category">分类</a></li> <li class="breadcrumb-item current">当前页</li> </ul> </nav> ``` 引用展示了类似的列表结构,通过超链接关联上级页面。 --- #### 二、CSS样式美化 添加分隔符(如`/`或`>`)并优化视觉效果: ```css .breadcrumb ul { list-style: none; padding: 0; margin: 0; display: flex; } .breadcrumb-item:not(:last-child)::after { content: ">"; margin: 0 10px; color: #999; } .breadcrumb-item a { text-decoration: none; color: #007bff; } .breadcrumb-item.current { color: #666; } ``` --- #### 三、动态生成(JavaScript) 根据当前URL路径自动生成层级: ```javascript function generateBreadcrumbs() { const path = window.location.pathname.split('/').filter(Boolean); let breadcrumbHTML = '<ul>'; let currentPath = ''; path.forEach((segment, index) => { currentPath += `/${segment}`; const name = decodeURIComponent(segment); breadcrumbHTML += index === path.length - 1 ? `<li class="current">${name}</li>` : `<li><a href="${currentPath}">${name}</a></li>`; }); document.querySelector('.breadcrumb').innerHTML = breadcrumbHTML + '</ul>'; } ``` --- #### 四、使用UI框架(如Element-UI) 通过现成组件快速实现: ```vue <el-breadcrumb separator="/"> <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item> <el-breadcrumb-item :to="{ path: '/category' }">分类</el-breadcrumb-item> <el-breadcrumb-item>当前页</el-breadcrumb-item> </el-breadcrumb> ``` 引用指出Element-UI的`el-breadcrumb`组件可直接配置分隔符与路由绑定。 --- #### 五、进阶优化 - **响应式处理**:在小屏设备中折叠中间层级 - **SEO友好**:添加JSON-LD结构化数据描述层级关系 - **状态管理**:在SPA中结合Vue Router或React Router动态更新路径 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值