고리타분한 개발자
[Vue JS] Practical Component Exercise #3: Tabs 본문
이번에는 Tab을 만들어 보도록 하겠습니다. 일단 탭에 들어갈 내용들을 리스팅 해보도록 하겠습니다.
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.1/css/bulma.min.css">
<style type="text/css">
body {
padding-top: 40px;
}
</style>
</head>
<body>
<div id="root" class="container">
<!-- ul#tabs>li*4>a[href=#] -->
<ul id="tabs">
<li>
<a href="#">About</a>
</li>
<li>
<a href="#">About Us</a>
</li>
<li>
<a href="#">About Our Culture</a>
</li>
</ul>
<!-- div.tab-panels -->
<div class="tab-panels">
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.js"></script>
<!-- <script src="main.js"></script> -->
</body>
</html>
리스팅 작업이 정상적으로 진행되면 bulma에서 tabs부분을 가져오도록 하겠습니다.
<div class="tabs">
<ul>
<li class="is-active"><a>Pictures</a></li>
<li><a>Music</a></li>
<li><a>Videos</a></li>
<li><a>Documents</a></li>
</ul>
</div>
bulma에서 가져온 코드를 우리가 만든 코드에 심어주면
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.1/css/bulma.min.css">
<style type="text/css">
body {
padding-top: 40px;
}
</style>
</head>
<body>
<div id="root" class="container">
<tabs>
<tab name="About Us" :selected="true">
<h1>Here is the content for the about us tab.</h1>
</tab>
<tab name="About Our Culture">
<h1>Here is the content for the about our culture tab.</h1>
</tab>
<tab name="About Our Vision">
<h1>Here is the content for the about our vision tab.</h1>
</tab>
</tabs>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.js"></script>
<script src="main.js"></script>
</body>
</html>
// main.js
Vue.component('tabs', {
template: `
<div>
<div class="tabs">
<ul>
<li class="is-active"><a>Pictures</a></li>
<li><a>Music</a></li>
<li><a>Videos</a></li>
<li><a>Documents</a></li>
</ul>
</div>
<div class="tabs-details"><slot></slot></div>
</div>
`
});
Vue.component('tab', {
template: `
<div><slot></slot></div>
`,
props: {
name: {
required: true
}
}
});
new Vue({
el: '#root',
});
위와같은 코드가 되겠죠? 그리고 결과값은 아래와 같습니다.
이제 우리가 지정해준 탭 이름(About과 같은...)을 뿌려주어야 할 차례인데요.
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.1/css/bulma.min.css">
<style type="text/css">
body {
padding-top: 40px;
}
</style>
</head>
<body>
<div id="root" class="container">
<tabs>
<tab name="About Us" :selected="true">
<h1>Here is the content for the about us tab.</h1>
</tab>
<tab name="About Our Culture">
<h1>Here is the content for the about our culture tab.</h1>
</tab>
<tab name="About Our Vision">
<h1>Here is the content for the about our vision tab.</h1>
</tab>
</tabs>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.js"></script>
<script src="main.js"></script>
</body>
</html>
// main.js
Vue.component('tabs', {
template: `
<div>
<div class="tabs">
<ul>
<li v-for="tab in tabs">
<a href="#">{{ tab.name }}</a>
</li>
</ul>
</div>
<div class="tabs-details"><slot></slot></div>
</div>
`,
data() {
return {
tabs: []
}
},
created() {
this.tabs = this.$children;
}
});
Vue.component('tab', {
template: `
<div><slot></slot></div>
`,
props: {
name: {
required: true
}
}
});
new Vue({
el: '#root',
});
이전에 하드코드로 리스트 되어있던 부분을 v-for을 사용하여서 간결하게 리스팅 해주었습니다.
<ul>
<li class="is-active"><a>Pictures</a></li>
<li><a>Music</a></li>
<li><a>Videos</a></li>
<li><a>Documents</a></li>
</ul>
to
<ul>
<li v-for="tab in tabs">
<a href="#">{{ tab.name }}</a>
</li>
</ul>
이번에는 클릭한 탭에 대하여 활성화 상태를 표시해보도록 하겠습니다.
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.1/css/bulma.min.css">
<style type="text/css">
body {
padding-top: 40px;
}
</style>
</head>
<body>
<div id="root" class="container">
<tabs>
<tab name="About Us" :selected="true">
<h1>Here is the content for the about us tab.</h1>
</tab>
<tab name="About Our Culture">
<h1>Here is the content for the about our culture tab.</h1>
</tab>
<tab name="About Our Vision">
<h1>Here is the content for the about our vision tab.</h1>
</tab>
</tabs>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.js"></script>
<script src="main.js"></script>
</body>
</html>
// main.js
Vue.component('tabs', {
template: `
<div>
<div class="tabs">
<ul>
<li v-for="tab in tabs" :class="{ 'is-active' : tab.selected }">
<a href="#">{{ tab.name }}</a>
</li>
</ul>
</div>
<div class="tabs-details"><slot></slot></div>
</div>
`,
data() {
return {
tabs: []
}
},
created() {
this.tabs = this.$children;
}
});
Vue.component('tab', {
template: `
<div><slot></slot></div>
`,
props: {
name: {
required: true,
},
selected: {
default: false
}
}
});
new Vue({
el: '#root',
});
이전과 달리 탭에 파란색으로 활성화 표시가 되었습니다. 하지만 다른 탭을 클릭하였을때 활성화 표시가 넘어가지질 않습니다. 그럼 제대로 작동되도록 코드를 변형시켜 보겠습니다.
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.1/css/bulma.min.css">
<style type="text/css">
body {
padding-top: 40px;
}
</style>
</head>
<body>
<div id="root" class="container">
<tabs>
<tab name="About Us" :selected="true">
<h1>Here is the content for the about us tab.</h1>
</tab>
<tab name="About Our Culture">
<h1>Here is the content for the about our culture tab.</h1>
</tab>
<tab name="About Our Vision">
<h1>Here is the content for the about our vision tab.</h1>
</tab>
</tabs>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.js"></script>
<script src="main.js"></script>
</body>
</html>
// main.js
Vue.component('tabs', {
template: `
<div>
<div class="tabs">
<ul>
<li v-for="tab in tabs" :class="{ 'is-active' : tab.isActive }">
<a href="#" @click="selectTab(tab)">{{ tab.name }}</a>
</li>
</ul>
</div>
<div class="tabs-details"><slot></slot></div>
</div>
`,
data() {
return {
tabs: []
}
},
created() {
this.tabs = this.$children;
},
methods: {
selectTab(selectedTab) {
this.tabs.forEach(tab => {
tab.isActive = (tab.name == selectedTab.name);
});
}
}
});
Vue.component('tab', {
template: `
<div><slot></slot></div>
`,
props: {
name: {
required: true,
},
selected: {
default: false
}
},
data() {
return {
isActive: false
}
},
mounted() {
this.isActive = this.selected;
}
});
new Vue({
el: '#root',
});
코드에 대한 설명은 다음과 같습니다.
1. 탭을 선택하면 selectTab 메서드를 호출합니다.
<a href="#" @click="selectTab(tab)">{{ tab.name }}</a>
2. selectTab은 isActive 프로퍼티를 true 혹은 false로 변경시켜 줍니다.
selectTab(selectedTab) {
this.tabs.forEach(tab => {
tab.isActive = (tab.name == selectedTab.name);
});
}
그럼 이번에는 각 탭마다 보여지는 문구가 다르게 만들어볼까요?
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.1/css/bulma.min.css">
<style type="text/css">
body {
padding-top: 40px;
}
</style>
</head>
<body>
<div id="root" class="container">
<tabs>
<tab name="About Us" :selected="true">
<h1>Here is the content for the about us tab.</h1>
</tab>
<tab name="About Our Culture">
<h1>Here is the content for the about our culture tab.</h1>
</tab>
<tab name="About Our Vision">
<h1>Here is the content for the about our vision tab.</h1>
</tab>
</tabs>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.js"></script>
<script src="main.js"></script>
</body>
</html>
// main.js
Vue.component('tabs', {
template: `
<div>
<div class="tabs">
<ul>
<li v-for="tab in tabs" :class="{ 'is-active' : tab.isActive }">
<a :href="tab.href" @click="selectTab(tab)">{{ tab.name }}</a>
</li>
</ul>
</div>
<div class="tabs-details"><slot></slot></div>
</div>
`,
data() {
return {
tabs: []
}
},
created() {
this.tabs = this.$children;
},
methods: {
selectTab(selectedTab) {
this.tabs.forEach(tab => {
tab.isActive = (tab.name == selectedTab.name);
});
}
}
});
Vue.component('tab', {
template: `
<div v-show="isActive"><slot></slot></div>
`,
props: {
name: {
required: true,
},
selected: {
default: false
}
},
data() {
return {
isActive: false
}
},
computed: {
href() {
return '#' + this.name.toLowerCase().replace(/ /g, '-');
}
},
mounted() {
this.isActive = this.selected;
}
});
new Vue({
el: '#root',
});
이로써 우리는 탭을 클릭하면 파일 경로가 변화하면서 원하는 내용만 보여지는 컴포넌트를 완성하게 되었습니다.
'Vue JS > Step By Step' 카테고리의 다른 글
[Vue JS] Practical Component Exercise #2: Modal (0) | 2017.12.05 |
---|---|
[Vue JS] Practical Component Exercise #1: Message (0) | 2017.12.04 |
[Vue JS] Components Within Components (0) | 2017.12.04 |
[Vue JS] Components 101 (0) | 2017.12.04 |
[Vue JS] The Need for Computed Properties (0) | 2017.12.04 |
Comments