タブ作成の要件は下記の通りです。
- v-forでタブを出力
- タブには共通のクラス、そのタブ用のクラス、アクティブになった時のクラスを付与
- タブによって表示するコンテンツはコンポーネントとし、is属性で出力
- タブのコンテンツ表示はtransitionを使用
読み込んでいるバージョンはVue 3 です。
CSSは機能が視認できる程度の最低限のものです。
See the Pen Vu.js3 tab components by blue moon (@blue-moon) on CodePen.
<template>
<ul class="tab">
<!-- 固定クラス、動的クラスを配列で設定 -->
<li
v-for="(tab, index) in tabs"
:key="index"
:class="[
'tab__item',
`tab__item--${tab}`,
{
'tab__item--active': activeTab === tab
}
]"
>
<label :for="tab" class="tab__label" v-text="tab" />
<input
:id="tab"
v-model="activeTab"
type="radio"
name="tabColor"
class="hidden"
@change="activeTab = tab"
/>
</li>
</ul>
<div class="tab-content">
<transition name="fade" mode="out-in">
<!-- アクティブタブに関連付けられたコンポーネントを表示 -->
<component :is="activeTab" />
</transition>
</div>
</template>
<script>
const contentBlue = {
template: `<p class="tab-content__text tab-content__text--blue">Blue content</p>`
};
const contentPink = {
template: `<p class="tab-content__text tab-content__text--pink">Pink content</p>`
};
const contentYellow = {
template: `<p class="tab-content__text tab-content__text--yellow">Yellow content</p>`
};
export default {
data() {
return {
activeTab: "pink",
tabs: ["blue", "pink", "yellow"]
};
},
components: {
// アクティブタブ名とコンポーネントを紐づける
blue: contentBlue,
pink: contentPink,
yellow: contentYellow
}
};
</script>
<style lang="scss">
:root {
--blue: #1f248c;
--pink: #f2357b;
--yellow: #f2e205;
}
.tab {
display: flex;
list-style: none;
gap: 1rem;
&__label {
cursor: pointer;
}
&__item {
font-size: 1.2rem;
font-weight: bold;
&--blue {
color: var(--blue);
}
&--pink {
color: var(--pink);
}
&--yellow {
color: var(--yellow);
}
&--active {
border-bottom: 2px solid;
}
}
}
.tab-content {
padding-left: 40px;
&__text {
padding: 1rem;
color: #fff;
width: 40em;
&--blue {
background-color: var(--blue);
}
&--pink {
background-color: var(--pink);
}
&--yellow {
background-color: var(--yellow);
}
}
}
.hidden {
display: none;
}
.fade-enter-active, .fade-leave-active {
transition: opacity .4s ease
}
.fade-enter-from, .fade-leave-to {
opacity: 0
}
</style>