Skip to content

Commit dec36a6

Browse files
committed
TabView 리팩토링
1 parent 6d6a835 commit dec36a6

File tree

13 files changed

+250
-315
lines changed

13 files changed

+250
-315
lines changed

src/View.js

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/app.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ import MainController from './controllers/MainController.js'
22
import './app.scss';
33

44
document.addEventListener('DOMContentLoaded', () => {
5-
MainController.init()
5+
new MainController()
66
})

src/app.scss

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,26 +37,6 @@ input[type=text] {
3737
border: 1px solid #ccc;
3838
}
3939

40-
ul.tabs {
41-
display: flex;
42-
}
43-
44-
.tabs li {
45-
display: inline-block;
46-
width: 50%;
47-
padding: 15px;
48-
text-align: center;
49-
box-sizing: border-box;
50-
border-bottom: 1px solid #ccc;
51-
background-color: #eee;
52-
color: #999;
53-
}
54-
55-
.tabs li.active {
56-
background-color: #2ac1bc;
57-
color: #fff;
58-
}
59-
6040
.list li {
6141
box-sizing: border-box;
6242
display: block;

src/controllers/MainController.js

Lines changed: 47 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -8,85 +8,69 @@ import SearchModel from '../models/SearchModel.js'
88
import KeywordModel from '../models/KeywordModel.js'
99
import HistoryModel from '../models/HistoryModel.js'
1010

11-
const tag = '[MainController]'
1211

13-
export default {
14-
init() {
15-
FormView.setup(document.querySelector('form'))
16-
.on('@submit', e => this.onSubmit(e.detail.input))
17-
.on('@reset', e => this.onResetForm())
12+
export default class MainController {
13+
constructor() {
14+
const formViewEl = document.querySelector('form')
15+
const tabViewEl = document.querySelector('#tabs')
16+
const keywordViewEl = document.querySelector('#search-keyword')
17+
const historyViewEl = document.querySelector('#search-history')
18+
const resultViewEl = document.querySelector('#search-result')
1819

19-
TabView.setup(document.querySelector('#tabs'))
20+
this.formView = new FormView(formViewEl)
21+
.on('@submit', e => this.search(e.detail.input))
22+
.on('@reset', () => this.renderView())
23+
24+
this.tabView = new TabView(tabViewEl)
2025
.on('@change', e => this.onChangeTab(e.detail.tabName))
2126

22-
KeywordView.setup(document.querySelector('#search-keyword'))
23-
.on('@click', e => this.onClickKeyword(e.detail.keyword))
27+
this.keywordView = new KeywordView(keywordViewEl)
28+
.on('@click', e => this.search(e.detail.keyword))
2429

25-
HistoryView.setup(document.querySelector('#search-history'))
26-
.on('@click', e => this.onClickHistory(e.detail.keyword))
30+
this.historyView = new HistoryView(historyViewEl)
31+
.on('@click', e => this.search(e.detail.keyword))
2732
.on('@remove', e => this.onRemoveHistory(e.detail.keyword))
2833

29-
ResultView.setup(document.querySelector('#search-result'))
34+
this.resultView = new ResultView(resultViewEl)
3035

3136
this.selectedTab = '추천 검색어'
3237
this.renderView()
33-
},
34-
search(query) {
35-
FormView.setValue(query)
36-
SearchModel.list(query).then(data => {
37-
this.onSearchResult(data)
38-
})
39-
},
40-
renderView() {
41-
console.log(tag, 'rednerView()')
42-
TabView.setActiveTab(this.selectedTab)
38+
}
4339

44-
if (this.selectedTab === '추천 검색어') {
45-
this.fetchSearchKeyword()
46-
HistoryView.hide()
47-
} else {
48-
this.fetchSearchHistory()
49-
KeywordView.hide()
50-
}
40+
async search(query) {
41+
this.formView.setValue(query)
42+
const data = await SearchModel.list(query)
43+
this.onSearchResult(data)
44+
}
5145

52-
ResultView.hide()
53-
},
54-
fetchSearchKeyword() {
55-
KeywordModel.list().then(data => {
56-
KeywordView.render(data)
57-
})
58-
},
59-
fetchSearchHistory() {
60-
HistoryModel.list().then(data => {
61-
const a = HistoryView.render(data)
62-
a.bindRemoveBtn()
63-
})
64-
},
65-
66-
onSubmit(input) {
67-
console.log(tag, 'onSubmit()', input)
68-
this.search(input)
69-
},
70-
onResetForm() {
71-
console.log(tag, 'onResetForm()')
72-
this.renderView()
73-
},
7446
onSearchResult(data) {
75-
TabView.hide()
76-
KeywordView.hide()
77-
HistoryView.hide()
78-
ResultView.render(data)
79-
},
47+
this.tabView.hide()
48+
this.keywordView.hide()
49+
this.historyView.hide()
50+
this.resultView.mount(data)
51+
}
52+
8053
onChangeTab(tabName) {
8154
this.selectedTab = tabName
8255
this.renderView()
83-
},
84-
onClickKeyword(keyword) {
85-
this.search(keyword)
86-
},
87-
onClickHistory(keyword) {
88-
this.search(keyword)
89-
},
56+
}
57+
58+
async renderView() {
59+
this.tabView.setActiveTab(this.selectedTab)
60+
61+
if (this.selectedTab === '추천 검색어') {
62+
const data = await KeywordModel.list()
63+
this.keywordView.mount(data)
64+
this.historyView.hide()
65+
} else {
66+
const data = await HistoryModel.list()
67+
this.historyView.mount(data).bindRemoveBtn()
68+
this.keywordView.hide()
69+
}
70+
71+
this.resultView.hide()
72+
}
73+
9074
onRemoveHistory(keyword) {
9175
HistoryModel.remove(keyword)
9276
this.renderView()

src/index.html

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@ <h2 class="container">검색</h2>
1616
</form>
1717

1818
<div class="content">
19-
<ul id="tabs" class="tabs">
20-
<li>추천 검색어</li>
21-
<li>최근 검색어</li>
22-
</ul>
19+
<div id="tabs"></div>
2320
<div id="search-keyword"></div>
2421
<div id="search-history"></div>
2522
<div id="search-result"></div>

src/models/SearchModel.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const data = [{
1111
]
1212

1313
export default {
14-
list(query) {
14+
list() {
1515
return new Promise(res => {
1616
setTimeout(() => {
1717
res(data)

src/views/FormView.js

Lines changed: 37 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,41 @@
11
import View from './View.js'
22

3-
const tag = '[FormView]'
3+
export default class FormView extends View {
4+
constructor (el) {
5+
super(el)
6+
this._inputEl = el.querySelector('[type=text]')
7+
this._resetEl = el.querySelector('[type=reset]')
8+
this._showResetBtn(false)
9+
this._bindEvents()
10+
return this
11+
}
12+
13+
_showResetBtn(show = true) {
14+
this._resetEl.style.display = show ? 'block' : 'none'
15+
}
16+
17+
_bindEvents() {
18+
this.on('submit', e => e.preventDefault())
19+
this._inputEl.addEventListener('keyup', e => this._onKeyup(e))
20+
this._resetEl.addEventListener('click', () => this._onClickReset())
21+
}
22+
23+
_onKeyup(e) {
24+
const enter = 13
25+
this._showResetBtn(this._inputEl.value.length)
26+
if (!this._inputEl.value.length) this.emit('@reset')
27+
if (e.keyCode !== enter) return
28+
this.emit('@submit', { input: this._inputEl.value })
29+
}
30+
31+
_onClickReset() {
32+
this.emit('@reset')
33+
this._showResetBtn(false)
34+
}
35+
36+
setValue(value = '') {
37+
this._inputEl.value = value
38+
this._showResetBtn(this._inputEl.value.length)
39+
}
440

5-
const FormView = Object.create(View)
6-
7-
FormView.setup = function (el) {
8-
this.init(el)
9-
this.inputEl = el.querySelector('[type=text]')
10-
this.resetEl = el.querySelector('[type=reset')
11-
this.showResetBtn(false)
12-
this.bindEvents()
13-
return this
14-
}
15-
16-
FormView.showResetBtn = function (show = true) {
17-
this.resetEl.style.display = show ? 'block' : 'none'
18-
}
19-
20-
FormView.bindEvents = function () {
21-
this.on('submit', e => e.preventDefault())
22-
this.inputEl.addEventListener('keyup', e => this.onKeyup(e))
23-
this.resetEl.addEventListener('click', e => this.onClickReset())
24-
}
25-
26-
FormView.onKeyup = function (e) {
27-
const enter = 13
28-
this.showResetBtn(this.inputEl.value.length)
29-
if (!this.inputEl.value.length) this.emit('@reset')
30-
if (e.keyCode !== enter) return
31-
this.emit('@submit', {
32-
input: this.inputEl.value
33-
})
34-
}
35-
36-
FormView.onClickReset = function () {
37-
this.emit('@reset')
38-
this.showResetBtn(false)
3941
}
40-
41-
FormView.setValue = function (value = '') {
42-
this.inputEl.value = value
43-
this.showResetBtn(this.inputEl.value.length)
44-
}
45-
46-
export default FormView

src/views/HistoryView.js

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,34 @@
11
import KeywordView from './KeywordView.js'
22

3-
const tag = '[HistoryView]'
3+
export default class HistoryView extends KeywordView {
4+
constructor(el) {
5+
super(el);
6+
this._messages.NO_KEYWORDS = '검색 이력이 없습니다'
47

5-
const HistoryView = Object.create(KeywordView)
6-
7-
HistoryView.messages.NO_KEYWORDS = '검색 이력이 없습니다'
8-
9-
HistoryView.getKeywordsHtml = function (data) {
10-
return data.reduce((html, item) => {
11-
html += `<li data-keyword="${item.keyword}">
12-
${item.keyword}
13-
<span class="date">${item.date}</span>
14-
<button class="btn-remove"></button>
15-
</li>`
16-
return html
17-
}, '<ul class="list">') + "</ul>"
18-
}
19-
20-
HistoryView.bindRemoveBtn = function () {
21-
Array.from(this.el.querySelectorAll('button.btn-remove')).forEach(btn => {
22-
btn.addEventListener('click', e => {
23-
e.stopPropagation()
24-
this.onRemove(btn.parentElement.dataset.keyword)
8+
return this;
9+
}
10+
11+
_getKeywordsHtml (data) {
12+
return data.reduce((html, item) => {
13+
html += `<li data-keyword="${item.keyword}">
14+
${item.keyword}
15+
<span class="date">${item.date}</span>
16+
<button class="btn-remove"></button>
17+
</li>`
18+
return html
19+
}, '<ul class="list">') + "</ul>"
20+
}
21+
22+
bindRemoveBtn () {
23+
Array.from(this.el.querySelectorAll('button.btn-remove')).forEach(btn => {
24+
btn.addEventListener('click', e => {
25+
e.stopPropagation()
26+
this._onRemove(btn.parentElement.dataset.keyword)
27+
})
2528
})
26-
})
29+
}
30+
31+
_onRemove (keyword) {
32+
this.emit('@remove', { keyword })
33+
}
2734
}
28-
29-
HistoryView.onRemove = function (keyword) {
30-
this.emit('@remove', {
31-
keyword
32-
})
33-
}
34-
35-
export default HistoryView

0 commit comments

Comments
 (0)