|
|
@@ -1,11 +1,11 @@
|
|
|
<template>
|
|
|
<div class="custom-button-group">
|
|
|
<div
|
|
|
- v-for="(item, index) in tabs"
|
|
|
- :key="index"
|
|
|
+ v-for="(item, index) in options"
|
|
|
+ :key="item.value || index"
|
|
|
class="group-item"
|
|
|
- :class="{ 'is-active': activeIndex === index }"
|
|
|
- @click="handleTabClick(index, item)"
|
|
|
+ :class="{ 'is-active': value === item.value }"
|
|
|
+ @click="handleTabClick(item)"
|
|
|
>
|
|
|
{{ item.label }}
|
|
|
</div>
|
|
|
@@ -15,34 +15,33 @@
|
|
|
<script>
|
|
|
export default {
|
|
|
name: 'ButtonGroup',
|
|
|
- // 如果你想从外部传入初始选中的值,可以通过 props
|
|
|
+ // 配置自定义 v-model
|
|
|
+ model: {
|
|
|
+ prop: 'value',
|
|
|
+ event: 'change'
|
|
|
+ },
|
|
|
props: {
|
|
|
- defaultIndex: {
|
|
|
- type: Number,
|
|
|
- default: 0
|
|
|
+ // 接收外部传入的当前选中值
|
|
|
+ value: {
|
|
|
+ type: [String, Number],
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ // 接收外部传入的按钮配置列表
|
|
|
+ options: {
|
|
|
+ type: Array,
|
|
|
+ default: () => []
|
|
|
+ // 数据格式应为: [{ label: '展示文本', value: '唯一标识' }]
|
|
|
}
|
|
|
},
|
|
|
- data() {
|
|
|
- return {
|
|
|
- activeIndex: this.defaultIndex,
|
|
|
- // 定义按钮组的数据和对应的标识(value)
|
|
|
- tabs: [
|
|
|
- { label: '总览', value: 'overview' },
|
|
|
- { label: '路口', value: 'intersection' },
|
|
|
- { label: '干线', value: 'arterial' },
|
|
|
- { label: '特勤', value: 'special' }
|
|
|
- ]
|
|
|
- };
|
|
|
- },
|
|
|
methods: {
|
|
|
- handleTabClick(index, item) {
|
|
|
- // 如果点击的是当前已选中的,则不重复触发
|
|
|
- if (this.activeIndex === index) return;
|
|
|
+ handleTabClick(item) {
|
|
|
+ // 避免重复点击触发
|
|
|
+ if (this.value === item.value) return;
|
|
|
|
|
|
- this.activeIndex = index;
|
|
|
-
|
|
|
- // 向父组件抛出 change 事件,并传递当前选中的 value
|
|
|
+ // 抛出 change 事件,更新 v-model 绑定的值
|
|
|
this.$emit('change', item.value);
|
|
|
+ // 额外抛出一个完整对象的事件,方便父组件需要获取 label 时使用
|
|
|
+ this.$emit('select', item);
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
@@ -52,27 +51,37 @@ export default {
|
|
|
/* 整个按钮组的外层容器 */
|
|
|
.custom-button-group {
|
|
|
display: flex;
|
|
|
- align-items: center;
|
|
|
- /* 假设整体宽度 400px,高度 40px,pxtorem 会自动转换 */
|
|
|
- width: 700px;
|
|
|
- height: 50px;
|
|
|
+ align-items: stretch; /* 让子元素填满高度 */
|
|
|
+ width: 100%; /* 自适应父容器宽度 */
|
|
|
+ min-height: 40px; /* 给一个基础最小高度,或者完全靠子元素的 padding 撑起 */
|
|
|
+
|
|
|
/* 整体边框颜色:淡蓝色半透明 */
|
|
|
border: 1px solid rgba(100, 150, 255, 0.6);
|
|
|
- background: rgba(20, 40, 80, 0.4); /* 未选中的底层背景色 */
|
|
|
+ background: rgba(20, 40, 80, 0.4);
|
|
|
box-sizing: border-box;
|
|
|
+
|
|
|
+ /* 可选:加上微小的圆角会让组件看起来更精致 */
|
|
|
+ border-radius: 4px;
|
|
|
+ overflow: hidden;
|
|
|
}
|
|
|
|
|
|
/* 单个按钮项 */
|
|
|
.group-item {
|
|
|
- flex: 1; /* 平分宽度 */
|
|
|
- height: 100%;
|
|
|
+ flex: 1; /* 平分剩余宽度 */
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
|
- color: #a0a5b0; /* 未选中时的灰白色字体 */
|
|
|
+
|
|
|
+ /* 使用 padding 替代固定的 height,自适应更好 */
|
|
|
+ padding: 8px 16px;
|
|
|
+
|
|
|
+ color: #a0a5b0;
|
|
|
font-size: 14px;
|
|
|
cursor: pointer;
|
|
|
transition: all 0.3s ease;
|
|
|
+ user-select: none; /* 防止双击选中文本 */
|
|
|
+ white-space: nowrap; /* 防止文字换行 */
|
|
|
+
|
|
|
/* 右侧分割线 */
|
|
|
border-right: 1px solid rgba(100, 150, 255, 0.6);
|
|
|
box-sizing: border-box;
|
|
|
@@ -92,8 +101,8 @@ export default {
|
|
|
/* 选中状态(激活态)的样式 */
|
|
|
.group-item.is-active {
|
|
|
/* 选中时的背景色:更亮、不透明度更高的蓝色 */
|
|
|
- background: rgba(70, 130, 255, 0.2);
|
|
|
- color: #ffffff; /* 选中时字体纯白 */
|
|
|
- font-weight: bold; /* 选中时字体加粗 */
|
|
|
+ background: rgba(70, 130, 255, 0.3);
|
|
|
+ color: #ffffff;
|
|
|
+ font-weight: bold;
|
|
|
}
|
|
|
</style>
|