Recent Posts
Recent Comments
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Tags
more
Today
Total
관리 메뉴

고리타분한 개발자

[Vue JS] Practical Component Exercise #3: Tabs 본문

Vue JS/Step By Step

[Vue JS] Practical Component Exercise #3: Tabs

sunlee334 2017. 12. 5. 05:49

이번에는 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',

});


이로써 우리는 탭을 클릭하면 파일 경로가 변화하면서 원하는 내용만 보여지는 컴포넌트를 완성하게 되었습니다.

Comments