본문 바로가기
Front-end/Vue3

20. Vue - 컴포넌트 기초(props, slot)

by devraphy 2021. 5. 21.

0. 예제코드

a) App.vue

<template>
  <MyBtn />
  <MyBtn />
  <MyBtn />
  <MyBtn />
</template>

<script>
import MyBtn from '~/components/MyBtn'
export default {
  components: {
    MyBtn
  }
}
</script> 

 

b) MyBtn.vue

<template>
  <div class="btn">
    Apple
  </div>
</template>

<style scoped>
  .btn {
    display: inline-block;
    margin: 4px;
    padding: 6px 12px;
    border-radius: 4px;
    background-color: gray;
    color: white;
    cursor: pointer;
  }

</style>

1. 컴포넌트의 재활용 

- 한번 만들어 놓은 컴포넌트는 재활용이 가능하다는 점이 Vue의 장점 중 하나다. 

- 컴포넌트를 만들어 놓고 해당 태그를 복사 붙여넣기만 하면 간단하게 재활용 할 수 있기 때문이다. 

 

a) props

- 기본적인 구조는 복사해서 사용한다고 해도 약간의 변화를 주고싶다면 어떻게 해야할까? 

- 그럴 때 사용할 수 있는 옵션이 props다. 

- 다음 예제 코드를 보면서 알아보자. 

 

[App.vue]

<template>
  <MyBtn />
  <MyBtn color="royalblue" />
  <MyBtn />
  <MyBtn />
</template>

<script>
import MyBtn from '~/components/MyBtn'
export default {
  components: {
    MyBtn
  }
}
</script> 

 

[MyBtn.vue] - style 부분 생략

<template>
  <div 
    :style="{ backgroundColor: color }"
    class="btn">
    Apple
  </div>
</template>

<script>
export default {
  props: {
    color: {
      type: String,
      default: 'gray'
    }
  }
}
</script>

1. 첫번째 포인트

- MyBtn.vue에서 props를 정의한 부분을 살펴보자. 

- color라는 속성을 정의하였다. type은 입력값의 형태를 의미하며, default는 기본값을 말한다. 

- 해당 컴포넌트를 재활용 할 때, color 라는 속성값이 입력되지 않으면 default 색상으로 지정되는 것을 의미한다. 

 

2. 두번째 포인트

- MyBtn.vue 에서 template 부분에 style속성에 v-bind 디렉티브를 사용한 것을 확인할 수 있다 (= 콜론). 

- backgroundColor 속성에 color라는 객체 데이터를 연결해 주었고, 이 color는 props에 정의한 부분을 사용하는 것이다. 

 

3. 세번째 포인트 

- App.vue에서 두번째 컴포넌트를 살펴보면 props에 선언했던 color를 royalblue로 설정했다.

- 결과는 다음 사진과 같다. 

 

출력화면

 

개발자 도구

 

4. v-bind를 사용한 최적화

- App.vue에서 작성한 코드를 v-bind를 이용해서 최적화 해본다면 다음과 같다. 

<template>
  <MyBtn />
  <MyBtn :color="color" />
  <MyBtn />
  <MyBtn />
</template>

<script>
import MyBtn from '~/components/MyBtn'
export default {
  components: {
    MyBtn
  },
  data() {
    return {
      color: 'royalblue'
    }
  }
}
</script> 

 

5. 알아두자

- 위에서 진행한 과정을 다시한번 생각해보자

- App.vue라는 부모 컴포넌트에서, MyBtn.vue라는 자식 컴포넌트에게 특정한 데이터를 전달하였다. 

- 즉, 부모-자식간의 데이터 통신을 가능하게 한 것이다. 

- 정리하자면, props를 통해서 부모-자식 컴포넌트 간의 데이터 통신이 가능하다는 것이다.

 


b) props를 활용한 class 바인딩

 

[MyBtn.vue]

<template>
  <div 
    :class="{ large: large }"
    :style="{ backgroundColor: color }"
    class="btn">
    Apple
  </div>
</template>

<script>
export default {
  props: {
    color: {
      type: String,
      default: 'gray'
    },
    large: {
      type: Boolean,
      default: false
    }
  }
}
</script>

<style scoped lang="scss">
  .btn {
    display: inline-block;
    margin: 4px;
    padding: 6px 12px;
    border-radius: 4px;
    background-color: gray;
    color: white;
    cursor: pointer;
    &.large {
      font-size: 20px;
      padding: 10px 20px;
    }
  }
</style>

 

[App.vue]

<template>
  <MyBtn />
  <MyBtn :color="color" />
  <MyBtn 
    large
    color="salmon" />
  <MyBtn />
</template>

<script>
import MyBtn from '~/components/MyBtn'
export default {
  components: {
    MyBtn
  },
  data() {
    return {
      color: 'royalblue'
    }
  }
}
</script> 

 

출력화면

- 출력화면에서 볼 수 있듯이, large 라는 props를 class로 바인딩을 시켜 보았다. 

- 더불어, props 데이터를 여러개 사용하여 크기와 색상을 변경시켜 보았다.

- 해당 코드를 이해하기 위해서 필요한 기본적인 지식은 위에서 배웠으니, 직접 코드를 이해해보면 좋을 것 같다. 


c) slot 태그를 이용한 문자열 커스텀

- 위에서 사용한 MyBtn.vue의 코드를 살펴보자.

- div 태그에 Apple 이라는 텍스트를 입력하여 모든 버튼이 Apple 이라는 문자열을 출력하도록 하였다. 

- 그렇다면 각 버튼이 다른 문자열을 출력하도록 할 수 있을까? 

- 이번에는 props를 사용하지 않고 slot이라는 태그를 이용해보자. 

 

[App.vue]

<template>
  <MyBtn>Banana</MyBtn>
  <MyBtn 
    :color="color">
    Apple
  </MyBtn>
  <MyBtn 
    large
    color="salmon">
    Cherry
  </MyBtn>
  <MyBtn>Mango</MyBtn>
</template>

<script>
import MyBtn from '~/components/MyBtn'
export default {
  components: {
    MyBtn
  },
  data() {
    return {
      color: 'royalblue'
    }
  }
}
</script> 

- MyBtn 태그를 주목하자 

- 이전에 컴포넌트는 모두 스스로 닫히는 구조를 갖고 있었다. 

- 그러나 위의 코드를 살펴보면 open 태그와 close 태그를 모두 갖고 있는 것을 확인할 수 있다. 

- 모든 컴포넌트가 반드시 스스로 닫히는 구조를 갖고 있는 것은 아니다. 

- 이처럼 태그사이에 문자열이나 어떤 값을 입력한다면 열고 닫는 태그를 사용할 수 있다. 

- 그렇다면 해당 문자열은 어떻게 어디를 통해서 출력되는 걸까? 그 해답은 slot 태그가 갖고 있다. 

 

 

[MyBtn.vue] - style 태그 생략(상동)

<template>
  <div 
    :class="{ large: large }"
    :style="{ backgroundColor: color }"
    class="btn">
    <slot></slot>
  </div>
</template>

<script>
export default {
  props: {
    color: {
      type: String,
      default: 'gray'
    },
    large: {
      type: Boolean,
      default: false
    },
  }
}
</script>

<style scoped lang="scss">
  .btn {
    display: inline-block;
    margin: 4px;
    padding: 6px 12px;
    border-radius: 4px;
    background-color: gray;
    color: white;
    cursor: pointer;
    &.large {
      font-size: 20px;
      padding: 10px 20px;
    }
  }
</style>

- template 태그 부분을 살펴보자 

- slot 이라는 새로운 태그가 삽입된 것을 확인할 수 있다. 

- slot은 각 컴포넌트의 열고 닫히는 태그사이에 삽입되는 입력값을 출력하는 역할을 한다. 

- 위의 코드를 보면, slot 태그는 div 내부에 위치하고 있다. 즉, 버튼 안쪽에서 출력을 한다는 의미다. 

- 결과는 다음과 같이 출력된다. 

출력화면


d) slot 태그는 단순히 문자열 출력만을 위한 것이 아니다.

- 위의 예제를 통해서 slot 태그의 사용법을 배워보았다. 

- 하지만, 위의 예제만 보면 slot 태그는 문자열 출력만을 위한 용도라고 이해하면 안된다. 

- 즉, slot 태그는 태그 사이(= <MyBtn>와 </MyBtn> 사이)에 입력되는 모든 내용을 출력하는 기능이다. 

- 다음 예제를 통해서 알아보자. 

 

[App.vue]

<template>
  <MyBtn>Banana</MyBtn>
  <MyBtn 
    :color="color">
    Apple
  </MyBtn>
  <MyBtn 
    large
    color="salmon">
    Cherry
  </MyBtn>
  <MyBtn><span style="color: orange;">Mango</span></MyBtn>
</template>

<script>
import MyBtn from '~/components/MyBtn'
export default {
  components: {
    MyBtn
  },
  data() {
    return {
      color: 'royalblue'
    }
  }
}
</script> 

- template 태그의 마지막 MyBtn 태그를 살펴보자. 

- 태그 사이에 span 태그를 삽입했다.

- 글씨 색상을 orange로 설정하였으며, Mango라는 문자열이 담겨있다. 

- 출력 결과는 다음과 같다. 

 

 

 

 

- 혹여나 이해가 어려운 경우를 위해, 다음 사진을 첨부한다. 

클릭하면 확대 됩니다.

 

'Front-end > Vue3' 카테고리의 다른 글

22. Vue - Emit(1)  (0) 2021.05.24
21. Vue - 속성 상속  (0) 2021.05.21
19. Vue - V model 수식어  (0) 2021.05.21
18. Vue - 폼 입력 바인딩(V-model)  (0) 2021.05.20
17. Vue - 이벤트 키 수식어  (0) 2021.05.20

댓글