Vue.js is属性でコンポーネントを切替え 動的クラスと固定クラスを付与してタブを作成

タブ作成の要件は下記の通りです。

  • 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>
タイトルとURLをコピーしました