본문 바로가기

Web/Vue.js & Nuxt.js

Vue.js 컴포넌트 공통 영역 처리하기 (feat. slot)

아래같은 형태의 컴포넌트를 여러 카테고리 게시판에서 공통으로 사용할 수 있도록 수정한다고 하자.

공통 컴포넌트 (하위 컴포넌트) - slot 적용 전

//게시글 제목과 작성자 이름 리스트를 뿌려주는 컴포넌트

<template>
  <div class="">
  	<ul class="list">
    	<li v-for="elem of contentElems">
        	<div>{{ elem.title }} </div>
            by {{ elem.userName }}
            | {{ elem.timeago}}
        </li>
    </ul>
  </div>
</template>

<script>
export default {
	computed:{
        contentElems(){
        	return '~~~Vuex Store'
        }
    }
}
</script>

<style lang="sass" scoped>	
</style>

대부분의 형태는 비슷한데 세부적인 것들이 다르다면 예를들어,

익명 게시판이 존재해 딱 그 게시판만 사용자 이름을 표시하지 않도록 작성하고 싶다면

그 컴포넌트만을 위해 새로운 컴포넌트를 만들 필요 없이 <slot>을 사용하면 된다.

<slot name="">을 사용하면 변동이 있을 수 있는 부분을 상위에서 처리하도록 할 수 있다.

주의할 점은 상위와 하위 컴포넌트에서 slot의 name 속성 값을 동일하게 설정해 주어야 한다.


공통 컴포넌트 (하위 컴포넌트) - slot 적용 후

//게시글 제목과 작성자 이름, 작성 일시 리스트를 뿌려주는 컴포넌트
//ListCompo.vue

<template>
  <div class="">
  	<ul class="list">
    	<li v-for="title of contentInfo">
        	<div>{{ title }}</div> 
        by 	<template slot="userName">
        	//상위 컴포넌트에서 작성하도록 비워둠
            </template> 
         |   <template slot="timeago">
        	//상위 컴포넌트에서 작성하도록 비워둠
            </template>
        </li>
    </ul>
  </div>
</template>

<script>
export default {
	props:['contentInfo'],
	computed:{
    	userName(){
        	return '~~~Vuex Store'
        },
        contentTitles(){
        	return '~~~Vuex Store'
        }
    }
}
</script>

<style lang="sass" scoped>	
</style>

 

익명 게시판 상위 컴포넌트

//상위의 익명 컴포넌트

<template>
  <div class="AnonList">
  	<list-compo :contentInfo="contentInfo">
    	<template slot="timeago">
        	{{ contentInfo.timeago }}
        </template>
    </list-compo>
  </div>
</template>

<script>
import ListCompo from './경로';
export default {
	components:{
    	ListCompo
    },
	computed:{
        contentInfo(){
        	return '~~~Vuex Store'
        }
    }
}
</script>

<style lang="sass" scoped>	
</style>

익명이 아닌 게시판 상위 컴포넌트

//상위의 익명이 아닌 컴포넌트

<template>
  <div class="NewsList">
  	<list-compo : contentInfo="contentInfo">
    	<template slot="timeago">
        	{{ contentInfo.timeago }}
        </template>
        <template slot="userName">
        	{{ contentInfo.userName }}
        </template>
    </list-compo>
  </div>
</template>

<script>
import ListCompo from './경로';
export default {
	components:{
    	ListCompo
    },
	computed:{
        contentInfo(){
        	return '~~~Vuex Store'
        },
    }
}
</script>

<style lang="sass" scoped>	
</style>

 

예제를 보면 알 수 있듯이, slot은 여러 개를 사용할 수 있다.

슬롯의 name 속성 값을 상위 컴포넌트와 일치하게 맞춰주는게 중요하다.