결과 화면

 

1. BaseAccordion 컴포넌트 만들기

  • components/base/BaseAccordion.vue

아코디언은 제목 부분을 클릭하면 내용 부분이 나타나는 레이아웃을 의미한다.

  1. title과 content로 나누어 html을 작성한다. 이때 content 부분은 펼쳐지는 느낌이 날 수 있도록 <transition> 컴포넌트를 이용한다.
  2. <transition> 컴포넌트의 @enter, @leave 메소드에 el.scrollHeight를 사용해서 내용에 따라서 높이값을 정할 수 있도록 한다.
  3. toggle 클릭 이벤트와 currentAccordion 속성을 이용해 title 부분을 클릭할 때마다 content 부분을 show/hide 시킨다.
  4. 공통으로 적용할 css/scss를 작성한다.
<template>
  <div class="base-accordion">
    <div
      class="title"
      @click="toggle">
      <slot name="title"/>
    </div>

    <transition
      name="accordion" appear
      @before-enter="beforeEnter" @enter="enter"
      @before-leave="beforeLeave" @leave="leave">
      <div
        v-show="currentAccordion"
        class="content">
        <slot name="content"/>
      </div>
    </transition>
  </div>
</template>

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

  data() {
    return {
      currentAccordion: false
    }
  },

  methods: {
    toggle() {
      this.currentAccordion = !this.currentAccordion
    },
    beforeEnter(el) {
      el.style.height = '0'
    },
    enter(el) {
      el.style.height = el.scrollHeight + 'px'
    },
    beforeLeave(el) {
      el.style.height = el.scrollHeight + 'px'
    },
    leave(el) {
      el.style.height = '0'
    }
  }
}
</script>

<style lang="scss" scoped>
.base-accordion {
  .title {
    padding: 20px;
    border-bottom: 1px solid #ddd;
    font-size: 16px;
    font-weight: 700;
    cursor: pointer;
  }

  .content {
    overflow: hidden;
    padding: 20px;
    background-color: #f5f5f5;
    transition: all 0.3s;
  }
}
</style>

 

2. 페이지에 BaseAccordion 컴포넌트 import 하기

  • pages/index.vue
  1. 만든 <BaseAccordion> 컴포넌트를 import 한다.
  2. <slot>으로 만든 부분에 내용이 들어갈 수 있도록 속성에 맞추어 내용을 작성한다.
<template>
  <TheLayout>
    <div class="accordion">
      <BaseAccordion>
        <h3 slot="title">첫번째 제목</h3>
        <p slot="content">
          내용입니다. 내용입니다. 내용입니다.
          내용입니다. 내용입니다. 내용입니다.
          내용입니다. 내용입니다. 내용입니다.
        </p>
      </BaseAccordion>

      <BaseAccordion>
        <h3 slot="title">두번째 제목</h3>
        <p slot="content">
          내용입니다. 내용입니다. 내용입니다.
          내용입니다. 내용입니다. 내용입니다.
        </p>
      </BaseAccordion>

      <BaseAccordion>
        <h3 slot="title">세번째 제목</h3>
        <p slot="content">
          내용입니다. 내용입니다. 내용입니다.
          내용입니다. 내용입니다. 내용입니다.
        </p>
      </BaseAccordion>
    </div>
  </TheLayout>
</template>

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

export default {
  name: 'Main',

  components: {
    TheLayout,
    BaseAccordion
  }
}
</script>

<style lang="scss" scoped>
.accordion {
  border: 1px solid #ddd;

  .base-accordion::v-deep {
    &:last-child {
      .title {
        border-bottom: 0;
      }
    }
  }
}
</style>

+ Recent posts