Result
View
export default class TabView extends View {
constructor() {
super(qs('#tab-view'));
this.template = new Template();
}
show() {}
bindEvents() {}
}
์ ์ ํ์ด์ง์ tab-view id๋ฅผ ๊ฐ์ง ํ๊ทธ์ ์์ ์ ์ํํ๋ค.
Result์ ๊ฐ์ด ํญ์ ๋ณด์ฌ์ค ๊ธฐ๋ฅ๊ณผ, ํญ์ ๋๋ฅด๋ ํ์๋ฅผ ํ๋ ๊ธฐ๋ฅ์ด ํ์
Controller
export default class Controller {
constructor(store, {searchFormView, searchResultView, tabView}) {
this.store = store;
this.searchFormView = searchFormView;
this.searchResultView = searchResultView;
this.tabView = tabView;
this.subscribeViewEvents();
this.render();
}
}
Controller์๋ View์ Model์ ์ ์ด๋ฅผ ์ํด ๋น์ฐํ tabView๊ฐ ์ถ๊ฐ ๋์ด์ผํ๋ค.
์ถ๊ฐ์ ์ผ๋ก View์์ ๊ตฌํํ tab์ ๋ณด์ฌ์ฃผ๋ ๊ธฐ๋ฅ๊ณผ ํด๋ฆญ๊ณผ ๊ฐ์ ์ด๋ฒคํธ๋ค์ ์ฒ๋ฆฌํ๋ ์์ ์ ๊ตฌํํด์ผํ๋ค.
subscribeViewEvents() {
this.tabView
.on('@select', (event) => this.select(event.detail.target));
}
์๋ฅผ ๋ค์ด, tabView์์ select๋ผ๋ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ ๋, chaining ๋ on method๋ก ์ด๋ฒคํธ๋ฅผ ์บ์นํ๊ณ ์ฒ๋ฆฌํ๋ค.
Model
export default class Store {
constructor(storage) {
if (!storage) throw "no storage";
this.storage = storage;
this.searchResult = [];
this.searchKeyword = "";
this.selectedTab = TabType.KEYWORD;
}
}
Store Model ์์๋ ์ด๋ค ํค์๋๋ฅผ ์ ํํ๋์ง์ ๋ํ ์ ๋ณด๋ฅผ ๋ด๊ธฐ ์ํ selectedTab ๋ณ์๊ฐ ์ถ๊ฐ๋๋ค.
๋งจ ์ฒ์, ๋ ๋๋ง ํ ๋ default๋ก ์ถ์ฒ๊ฒ์์ด๋ฅผ ์ ํํ๋ค.
Quest
Q. ๊ฐ ํญ์ ํด๋ฆญํ๋ฉด ํญ ์๋ ๋ด์ฉ์ด ๋ณ๊ฒฝ๋๋๋ก ํ๋ค.
์ฐ์ , ๊ฐ์์ ์ฑํฐ ์ ํญ ์๋ ๋ด์ฉ์ tab-content๋ก ๋ค๋ฅธ ์ฑ ์์ ๊ฐ์ง๊ณ ์์ผ๋ฏ๋ก ์ ์ ๋น์๋๋ค.
bindEvents() {
on(this.element, "click", event => this.handleClick(event));
}
handleClick(event) {
const { target } = event;
this.emit("@select", { target });
}
๋๋ TabView์์ ํด๋ฆญ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด ํด๋ฆญํ ์ฃผ์ฒด๋ฅผ @select ์ด๋ฒคํธ๋ก ๋ฐํํ๋ค.
๊ทธ๋ฆฌ๊ณ ์์ Controller์์ ์์ฑํ, subscribeEvents ๋ฉ์๋์์ tabView๋ก ๋ถํฐ @select ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด ์ฒ๋ฆฌํ๋ค.
Controller ์ ์ฅ์์, ์ด๋ค ํ๊ทธ๋ฅผ ํด๋ฆญํ๋์ง ๋ช ํํ ์ ์ ์๋ค. (TabView์์ ์๋ ค์ค)
select(target) {
const tab = target.dataset.tab;
this.store.select(tab);
this.tabView.show(this.store.selectedTab);
}
๊ทธ๋ฆฌ๊ณ target์ tab ์ ๋ณด๋ฅผ ๊ฐ์ ธ์์ store์ selectedTab ๋ณ์๋ก ์ง์ ํ๋ค.
๊ทธ๋ฆฌ๊ณ tabView๋ฅผ ๋ค์ ๋ ๋๋ง ํ๋ค.
๊ฐ์ฌ๋๊ป์๋ utility(helper.js)์ delegate๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค.
export function delegate(target, eventName, selector, handler) {
const emitEvent = (event) => {
const potentialElements = qsAll(selector, target);
for (const potentialElement of potentialElements) {
if (potentialElement === event.target) {
return handler.call(event.target, event);
}
}
};
on(target, eventName, emitEvent);
}
1. ์์ tag์ ๋ชจ๋ ํ์ ์์๋ฅผ ๋ค ๊ฐ์ ธ์จ๋ค.
2. ์์ tag์ ๋ชจ๋ ํ์ ์์ ์ค ๋ธ๋ผ์ฐ์ ์์ event๊ฐ ๋ฐ์ํ ์์์ ๊ฐ์ ๊ฒ์ ๋ฐํํ๋ค.
3. ์์ tag์ ์ด๋ฒคํธ๋ก ์ถ๊ฐํ๋ค.
๋ด ์ฝ๋์ ๋ฌธ์ ์ ์ li ํ๊ทธ ์ธ์ ๋ค๋ฅธ ํ๊ทธ๊ฐ ์ถ๊ฐ๋์์ ๋๋ ์ด๋ฒคํธ๊ฐ ๋ฐํ๋๋ค๋ ์ ์ด๋ค.
์์ ์์ฑํ ์ฝ๋์์ bindEvents๋ง delegate๋ก ์์ ํ๋ฉด ๋๋ค.
handleClick(event) {
const tab = event.target.dataset.tab;
this.emit("@tabchange", { tab });
}
this.tabView
.on('@tabchange', (event) => {this.select(event.detail.tab);});
select(tab) {
this.store.select(tab);
this.tabView.show(this.store.selectedTab);
}
๊ทธ๋ฆฌ๊ณ ์ถ๊ฐ๋ก ๋ช ํํ ํด์ฃผ์๋ค.
TabView์์ click event๊ฐ tab change๋ง ์กด์ฌํ์ง ์๊ณ , ์ถ๊ฐ์ ์ธ event๊ฐ ๋ฐ์ํ ์ ์๋ค.
-> event ๋ฐํ ์ ๋ช ํํ ์ด๋ฒคํธ ๋ช ๊ณผ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ๋ฐํํ๋ค.
Tip
class Template {
getTabList() {
return `
<ul class="tabs">
${Object.values(TabType)
.map(tabType => ({ tabType, tabLabel: TabLabel[tabType] }))
.map(this._getTab)
.join("")}
</ul>
`;
}
_getTab({tabType, tabLabel}) {
return `
<li data-tab=${tabType}>
${tabLabel}
</li>
`;
}
}
๋ ๋๋ง์ ์ํ Template ํด๋์ค์์ _getTap method๋ก map ํจ์๋ฅผ ๋๋ฆฌ๋ ๊ณผ์ ์์ $[tabLabel] ๋ฐฑํฑ ๋ถ๋ถ์ด ๊ณ์ํด์ undefined๋ก ์ถ๋ ฅ๋๋ค.
์ด์ ๋ js์์ ์ค๊ดํธ, {}๋ฅผ ์ฌ์ฉํ๋ฉด ํ๋ผ๋ฏธํฐ ์ ๋ฌ์ด ์๋๊ณ mapping์ด ๋๋ ๊ฒ์ด๋ค. ์ฆ, getTabList() ๋ฉ์๋์์ ์ฒซ๋ฒ ์งธ map ๋ฉ์๋์์ { tabType, tabLabel } ๋ก ๋ฐ๊พธ์๊ณ , ๊ทธ ๋ค์ map ๋ฉ์๋์์ _getTab์ผ๋ก ๋ณํํ๋ ์ค tabLabel์ด tabLable๋ก ์คํ๊ฐ ๋ฐ์ํด์ ๋งคํ์ด ๋์ง ์๋ ๋ฌธ์ ์๋ค.
์ด ํ์ handleClick ๋ฉ์๋์ ๊ฐ์ด ์์ฑํ ๋๋ ์ ๊ฒฝ์จ์ผํ๋ ๋ถ๋ถ์ด๋ค.
'JavaScript > Vanila' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Vanila js] ์ต๊ทผ ๊ฒ์ ๊ตฌํํ๊ธฐ (0) | 2024.08.02 |
---|---|
[Vanila js] ํค์๋ ๊ฒ์ ๊ตฌํํ๊ธฐ (0) | 2024.08.02 |
[Vanila js] ๊ฒ์ ๊ฒฐ๊ณผ ๊ธฐ๋ฅ ๊ตฌํ (0) | 2024.07.31 |
[Vanila js] ๊ฒ์ ๊ธฐ๋ฅ ๊ตฌํํ๊ธฐ (0) | 2024.07.31 |
[Vanila.js] ์ฌ์ ์ฝ๋ ์ดํดํ๊ธฐ (0) | 2024.07.31 |