vue3 封装简单的 tabs 切换组件
背景:公司项目要求全部换成 vue3 ,而且也没有应用像 element-ui 一类的UI组件,用到的公共组件都是根据项目需求封装的,下面是使用vue3实现简单的tabs组件,我只是把代码分享出来,实现思路如果有需要等我项目不忙了在更,希望大家多提些建议,共同学习共同进步。
tab-group.vue
<template>
<div class="tab-group">
<!-- tabRef 这块本来是用来实现下划线动态切换特效的,暂时没有写效果 -->
<div ref="barRef" class="tab-bar" :style="{ width: widthRef + 'px' }"></div>
<div ref="titsRef" class="tab-header" layout="row" layout-wrap>
<div
ref="titRef"
:class="[{ active: activeKey == item.props.actKey }, 'tab-nav']"
v-for="(item, index) in tabTitLists"
:key="item"
@click="onTabClick($event, item, index)"
>
{{ item.props.label }}
</div>
</div>
<div class="tab-panel">
<slot></slot>
</div>
</div>
</template>
<script>
import { ref, onMounted, provide } from "vue";
export default {
props: {
defaultKey: {
type: String,
default: "1",
},
},
setup(props, context) {
const tabTitLists = context.slots.default();
let activeKey = ref(props.defaultKey); //当前key
provide("activeKey", activeKey);
const barRef = ref(null);
const titRef = ref(null);
let widthRef = ref();
onMounted(() => {
// 设置状态线初始化宽度
widthRef.value = titRef.value.clientWidth;
});
function onTabClick(event, tab, index) {
activeKey.value = tab.props.actKey;
}
return {
tabTitLists,
barRef,
titRef,
widthRef,
onTabClick,
activeKey,
};
},
};
</script>
<style scoped lang="less">
.tab-group {
// .tab-bar {
// position: absolute;
// left: 0;
// border-bottom: 2px solid #409eff;
// }
.tab-header {
&:after {
content: "";
width: 100%;
border-bottom: 2px solid #ddd;
}
}
.tab-nav {
color: #5c5c5c;
font-size: 14px;
line-height: 40px;
display: inline-block;
margin-right: 3em;
cursor: pointer;
border-bottom: 2px solid transparent;
&.active {
color: #2f5cd5;
border-bottom-color: #2f5cd5;
}
}
.tab-panel{
padding: 15px;
}
}
</style>
tab-panel.vue
<template>
<div v-show="actKey == activeKey">
<slot></slot>
</div>
</template>
<script>
import { ref, inject } from "vue";
export default {
props: {
actKey: {
type: String,
default: "1",
},
label: {
type: String,
default: "全部",
},
},
setup() {
let activeKey = ref();
activeKey = inject("activeKey");
return { activeKey };
},
};
</script>
应用
<template>
<div>
<tab-group defaultKey="1">
<tab-panel label="进行中" actKey="1">进行中-内容</tab-panel>
<tab-panel label="已结束" actKey="2">已结束-内容</tab-panel>
<tab-panel label="全部" actKey="3">全部带-内容</tab-panel>
</tab-group>
</div>
</template>
<script>
import tabGroup from "../common/tabs/tab-group.vue";
import tabPanel from "../common/tabs/tab-panel.vue";
export default {
components: {
tabPanel,
tabGroup,
},
setup(props, context) {
return {};
},
};
</script>
生活中不可能到处顺利,包括工作!