本文章是对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>