142 lines
3.0 KiB
Vue
142 lines
3.0 KiB
Vue
<template>
|
||
<!-- 按钮切换 -->
|
||
<div v-if="buttonMode" class="button-nav">
|
||
<button v-for="m in menus" :key="m" @click="handleClick(m)"
|
||
:data-text="m"
|
||
:class="[m === currentMenu ? 'active' : '']"
|
||
></button>
|
||
</div>
|
||
<!-- 标签切换 -->
|
||
<div v-else class="custom-tabs" style="height: 100%; width: 100%">
|
||
<el-tabs class="tag-nav" v-model="currentMenu" style="height: 100%" @tab-click="handleTabClick">
|
||
<el-tab-pane v-for="(m, idx) in menus" :key="m" :label="idx == 0 ? `\u2002${m}\u2002` : `\u3000${m}\u3000`"
|
||
:name="m">
|
||
<slot :name="`tab${idx + 1}`"></slot>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
name: "ButtonNav",
|
||
props: {
|
||
menus: {
|
||
type: Array,
|
||
required: true,
|
||
default: () => [],
|
||
validator: (val) => val.length > 0,
|
||
},
|
||
buttonMode: {
|
||
type: Boolean,
|
||
default: true,
|
||
},
|
||
// 新增:支持外部传入选中值(v-model 绑定)
|
||
value: {
|
||
type: String,
|
||
default: "",
|
||
},
|
||
},
|
||
data() {
|
||
return {
|
||
currentMenu: "",
|
||
};
|
||
},
|
||
created() {
|
||
// 优先使用外部传入的 value,否则默认第一个
|
||
this.currentMenu = this.value || this.menus[0];
|
||
},
|
||
watch: {
|
||
// 监听外部 value 变化,同步到内部 currentMenu
|
||
value(newVal) {
|
||
this.currentMenu = newVal;
|
||
},
|
||
// 监听内部 currentMenu 变化,通知外部
|
||
currentMenu(val) {
|
||
this.$emit("input", val); // 触发 v-model 同步
|
||
this.$emit("change", val); // 保留原 change 事件
|
||
},
|
||
},
|
||
methods: {
|
||
// 按钮点击事件
|
||
handleClick(m) {
|
||
this.currentMenu = m;
|
||
},
|
||
// 标签点击事件(el-tabs 自带)
|
||
handleTabClick(tab) {
|
||
this.currentMenu = tab.name;
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<!-- 样式不变 -->
|
||
<style scoped lang="scss">
|
||
.button-nav {
|
||
width: 100%;
|
||
display: flex;
|
||
gap: 12px;
|
||
|
||
* {
|
||
user-select: none;
|
||
}
|
||
|
||
button {
|
||
cursor: pointer;
|
||
appearance: none;
|
||
outline: none;
|
||
border: none;
|
||
background: #fff;
|
||
border-radius: 8px;
|
||
padding: 15px;
|
||
color: #888;
|
||
letter-spacing: 2px;
|
||
flex: 1;
|
||
box-sizing: padding-box;
|
||
position: relative;
|
||
|
||
&::after {
|
||
content: attr(data-text);
|
||
position: absolute;
|
||
top: 5px;
|
||
left: 50%;
|
||
font-size: 16px;
|
||
font-weight: 500;
|
||
transform: translate(-50%);
|
||
}
|
||
|
||
&.active {
|
||
color: #111;
|
||
//border-bottom: 2px solid #0b58ff;
|
||
box-shadow: 0px 2px 1px 1px #0b58ff;
|
||
}
|
||
}
|
||
}
|
||
</style>
|
||
|
||
<style scoped>
|
||
.custom-tabs>>>.el-tabs__header {
|
||
margin-bottom: 8px;
|
||
display: inline-block;
|
||
/* transform: translateY(-12px); */
|
||
}
|
||
|
||
.custom-tabs>>>.el-tabs__item {
|
||
padding-left: 0px !important;
|
||
padding-right: 0px !important;
|
||
line-height: 36px !important;
|
||
height: 36px;
|
||
}
|
||
|
||
.custom-tabs>>>.el-tabs__content {
|
||
height: calc(100% - 42px);
|
||
}
|
||
|
||
.custom-tabs>>>.el-tab-pane {
|
||
box-sizing: border-box;
|
||
height: 100%;
|
||
padding: 20px;
|
||
border: 10px solid #f002;
|
||
}
|
||
</style>
|