결과 화면

 

1. BaseTab 컴포넌트 만들기

  • components/base/BaseTab.vue
  1. tab이 몇 개인지 모르니 배열 타입으로 props 받는다.
  2. key와 currentTab에 따라서 탭의 on/off 상태를 나타낸다.
  3. 클릭하면 탭이 변경되어야 하기 때문에 $emit으로 클릭 이벤트를 만든다.
  4. 공통으로 적용할 css/scss를 작성한다.
<template>
  <div class="base-tab">
    <ul>
      <li
        v-for="(item, key) in tab"
        :key="`tab-${key}`"
        :class="{ 'on': key === currentTab }"
        @click="$emit('click', key)">
        {{ item.name }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'BaseTab',

  props: {
    tab: {
      type: Array,
      required: true
    },
    currentTab: {
      type: Number,
      default: 0
    }
  }
}
</script>

<style lang="scss" scoped>
.base-tab {
  margin-bottom: 30px;

  ul {
    display: flex;
    justify-content: start;
    align: center;
    gap:  20px;

    li {
      padding: 0 5px;
      border-bottom: 2px solid transparent;
      color: #888;
      font-size: 20px;
      font-weight: 700;
      transition: all 0.3s;
      cursor: pointer;

      &:hover {
        color: #333;
      }

      &.on {
        color: #333;
        border-bottom: 2px solid #333;
      }
    }
  }
}
</style>

 

2. 페이지에 BaseTab import 하기

  • pages/index.vue
  1. 만든 <BaseTab> 컴포넌트를 import 한다.
  2. currentTab, tab 속성을 만들어 <BaseTab>에 데이터를 넘긴다.
  3. changeTab() 클릭 이벤트를 만들어 currentTab이 <BaseTab>의 key 값과 동일하게 만든다.
  4. v-if를 통해서 currentTab 값에 따라 영역을 나타나고, 안 보이게 한다.
<template>
  <TheLayout>
    <BaseTab
      :tab="tab"
      :currentTab="currentTab"
      @click="changeTab"/>

    <section v-if="currentTab === 0">
      탭 1 영역입니다.
    </section>

    <section v-if="currentTab === 1">
      탭 2 영역입니다.
    </section>
  </TheLayout>
</template>

<script>
import TheLayout from '@/components/layout/TheLayout'

export default {
  name: 'Index',

  components: {
    TheLayout
  },

  data() {
    return {
      currentTab: 0,
      tab: [
        { name: '탭 1' },
        { name: '탭 2' }
      ]
    }
  },

  methods: {
    changeTab(key) {
      this.currentTab = key
    }
  }
}
</script>

+ Recent posts