본문 바로가기
Programming/Vue.js

Vue.js에서 Props 대신 Slot! 하위 컴포넌트에게 데이터 전송

by 주리니e 2022. 12. 20.
728x90

Vue.js에서 Props 대신 Slot! 하위 컴포넌트에게 데이터 전송

 


Props를 이용한 하위 컴포넌트에게 데이터를 전송하는 방식 말고도 슬롯(Slot)을 이용할 수도 있다. Slot은 컴포넌트의 재사용성을 높여주며 특정 컴포넌트에 등록된 하위 컴포넌트의 마크업을 확장하거나 재정의할 수 있다. Slot에는 몇가지 단점이 존재하는데  다량의 데이터를 Slot으로 전송하는 경우 Props보다 복잡할 수 있다. 또한 Slot으로는 하위 컴포넌트의 HTML태그의 attirbute에 값을 바인딩할 수 없고 오로지 HTML로서만 사용한 다는점이다. 허나 간단한 데이터나 HTML을 재정의하는 경우에는 Props문법보다 훨씬 간결하고 유용하게 사용할 수 있으므로 상황에 맞게 Slot과 Props를 선택하여 사용하면 된다.


  • 기본 Slot 사용방법
<!-- 상위 컴포넌트 -->
<template>
  <ChildComponent>
    <div>
      slot으로 전송할 HTML 또는 데이터
      <button>왼쪽 버튼</button>
      <button>오른쪽 버튼</button>
    </div>
  </ChildComponent>
</template>
<!-- 하위 컴포넌트 -->
<template>
  <div>
    <slot></slot>
  </div>
</template>

 

  • Named Slot 사용방법
<!-- 상위 컴포넌트 -->
<template>
  <ChildComponent>
    <template v-slot:class><div>Named Slot class : {{userArray[i].class}}</div></template>
    <template v-slot:color><div>Named Slot color : {{userArray[i].color}}</div></template>
  </ChildComponent>
</template>
<!-- 하위 컴포넌트 -->
<template>
  <div>
    <slot name="class"></slot>
    <slot name="color"></slot>
  </div>
</template>

 

  • 샘플 프로젝트 생성
> vue create slot-test

샘플 프로젝트를 생성하면 App.vue는 상위(부모) 컴포넌트로서 하위(자식) 컴포넌트인 HelloWorld를  쓰고 있다. 샘플 프로젝트의 소스를 보면 App.vue로부터 HelloWorld.vue로 이미 이름이 msg인 String 값을  Props를 이용하여 전송하고 있는 것을 확인할 수 있다.



  • Props를 이용한 하위 컴포넌트로 데이터 전송

지난 시간에 props를 이용하여 최상위 컴포넌트인 App.vue는 그 하위 컴포넌트인 HelloWorld.vue에 msg와 userArray 데이터를 props를 이용하여 전송, HelloWorld.vue 컴포넌트는 msg 데이터를 출력하고 userArray 개수만큼 그 하위 컴포넌트인 UserView.vue 컴포넌트를 생성하고 userData정보를 전송, userView.vue 컴포넌트는 userData 정보를 받아 출력한다. 이번 시간에 진행할 Slot과 비교하면 좋은 내용이니 아래 링크를 참고하자.

 

Vue.js에서 Props를 이용한 하위 컴포넌트에게 데이터 전송

Vue.js에서 Props를 이용한 하위 컴포넌트에게 데이터 전송 props는 properties 의 줄임말로 상위 컴포넌트가 하위 컴포넌트에게 데이터를 전달해줘야 할 때 props를 사용한다. 단방향 데이터 흐름을 가

jiurinie.tistory.com



  • 데이터 전송

최상위 컴포넌트인 App.vue는 그 하위 컴포넌트인 HelloWorld.vue에 msg와 userArray 데이터를 props를 이용하여 전송한다. HelloWorld.vue 컴포넌트는 msg 데이터를 출력하고 userArray 개수만큼 그 하위 컴포넌트인 UserView.vue 컴포넌트를 생성하고 userData정보를 slot을 이용하여 전송한다. userView.vue 컴포넌트는 userData 정보를 받아 출력한다.



  • App.vue
<template>
  <div>
    <HelloWorld msg="Welcome to Your Vue.js App" :userArray="userArray" />
  </div>
</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";

export default {
  name: "App",
  data() {
    return {
      userArray: [
        {
          userId: 1,
          id: 1,
          title:
            "laboriosam mollitia et enim quasi adipisci quia provident illum",
          completed: false,
          class: 'user-info',
          color: 'red'
        },
        {
          userId: 1,
          id: 2,
          title: "quis ut nam facilis et officia qui",
          completed: false,
          class: 'user-info',
          color: 'blue'
        },
      ],
    };
  },
  components: {
    HelloWorld,
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>



  • HelloWorld.vue

기본 Slot으로 span HTML 태그 안에 userArray[i]의 title을 데이터로 전송한다. Named Slot의 v-slot 문법을 이용하여 'class'와 'color'의 이름으로 데이터를 전송한다. 

<template>
  <div>
    <img alt="Vue logo" src=".././assets/logo.png" />
    <div class="hello">
      <h1>{{ msg }}</h1>
      <UserView v-for="(a, i) in userArray" :key="i" >
        <span>{{userArray[i].title}}</span>
        <template v-slot:class><div>Named Slot class : {{userArray[i].class}}</div></template>
        <template v-slot:color><div>Named Slot color : {{userArray[i].color}}</div></template>
      </UserView>
    </div>
  </div>
</template>

<script>
import UserView from "./UserView.vue";

export default {
  name: "HelloWorld",
  props: {
    msg: String,
    userArray: Array,
  },
  components: {
    UserView,
  },
};
</script>
<style></style>



  • UserView.vue

이름없는 기본 Slot의 경우에는 Slot태그로만 감싸주면 되며, Named Slot의 경우에는 name="이름"을 지정하는 방식으로 데이터나 HTML을 받아올 수 있다.

<template>
  <div style="margin-bottom: 50px">
    <h4 style="margin-top: 20px">Slot으로 받은 데이터</h4>
    <div>
      slot으로 받은 title : <slot></slot>
      <slot name="class"></slot>
      <slot name="color"></slot>
    </div>
    <p></p>
  </div>
</template>

<script>
export default {
  name: "UserView",
  props: {
    userData: Object,
  },
};
</script>

<style></style>

 

  • Slot을 이용한 데이터 출력 화면

728x90

댓글