-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[#5] 폴더구조 수정 및 라우팅 설정 #6
Changes from 15 commits
bf5033d
eebca65
21d8018
c111101
5b8a93b
9cf6e5c
3367425
f2fbe99
fa6690e
223df14
5ad344f
4997f66
7f81a49
48670f4
051964b
e3f8c7b
0394ff4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import './style.css'; | ||
import { router } from './core/router/Router.js'; | ||
|
||
document.addEventListener('DOMContentLoaded', () => { | ||
router.init(); | ||
}); |
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import './Header.js'; | ||
import './Footer.js'; | ||
import '../../core/router/RouterOutlet.js'; | ||
|
||
export default class Layout extends HTMLElement { | ||
static observedAttributes = ['header', 'footer']; | ||
|
||
connectedCallback() { | ||
this.render(); | ||
} | ||
|
||
render() { | ||
const headerTag = this.getAttribute('header') || ''; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오호...? 이 코드는 엄청 많이 생길거 같은데... 너무 리액트스럽게 쓰고자 고민하고 계신거 같기도 하네요. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 레이아웃에 관련된 리뷰와 같이 과한 설계를 한 느낌이 약간 듭니다.. 유연한 레이아웃 변경을 위해 처리했는데 오히려 관리할 리소스가 늘은 느낌이 드는 것 같습니다 |
||
const footerTag = this.getAttribute('footer') || ''; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 헤더와 푸터를 이렇게 다이나믹하게 주입해주는 장점이 뭘까여? 레이아웃안에 헤더와 푸터를 선언해놓은 것과 대비한 장점이 궁금해요. 헤더와 푸터가 자주 바뀌는 대상일까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 헤더와 푸터를 다이나믹하게 처리함으로써 유연한 레이아웃 관리가 가능하여 레이아웃이 다른 페이지가 나올 경우 쉽게 변경이 가능합니다. 해더,푸터는 자주 바뀌는 대상은 아니지만 바뀔 수도 있는 대상입니다. 그렇기 때문에 변경 가능성을 열어두었습니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 헤더나 푸터를 주입받도록 한다고 해도 결국에는 custom tag 를 전달하는 식일테고 이 변경이 라우터마다 config 로 추가되는게 유연한 구조인지 의문이 드네요. 프로젝트 완성되어 갈즈음 얼만큼 활용되었는지 봐도 좋을거 같네요. 지금으로서는 섣부른 확장고려 인거 같긴해요. 애초에 페이지가 하나짜리라고도 하셨기에..? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 네 맞습니다..페이지가 하나인데... 저번 멘토링에 레이아웃 구조가 확장에 유연하지 않다라고 말씀 하신게 생각나서 이렇게 한번 해볼까?라는 생각으로 수정을 해 본 케이스입니다 |
||
this.innerHTML = ` | ||
${headerTag ? `<${headerTag}></${headerTag}>` : ''} | ||
<router-outlet></router-outlet> | ||
${footerTag ? `<${footerTag}></${footerTag}>` : ''} | ||
`; | ||
} | ||
} | ||
|
||
customElements.define('app-layout', Layout); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import Layout from '../../components/layout/Layout.js'; | ||
import RouterOutlet from './RouterOutlet.js'; | ||
import { routes } from './RouterConfig.js'; | ||
|
||
class Router { | ||
static instance = null; | ||
|
||
constructor() { | ||
if (Router.instance) { | ||
return Router.instance; | ||
} | ||
Router.instance = this; | ||
|
||
this.routes = new Map(Object.entries(routes)); | ||
|
||
window.addEventListener('popstate', () => { | ||
this.handleRoute(window.location.pathname); | ||
}); | ||
|
||
document.addEventListener('click', (e) => { | ||
const link = e.target.closest('[data-link]'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a tag 를 쓰지않고 커스텀 dataset을 이용하는 장점과 단점은 뭘까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dataset을 사용하면 closest을 통해 클릭 된 요소로부터 속성을 가진 가장 가까운 상위 요소를 찾게 되면서 원하는 라우팅 링크만 정확하게 선택 할 수 있다는 장점이 있습니다. 후자의 단점은 a 태그와 dataset을 함께 사용하면 해결 �됩니다.
|
||
if (link) { | ||
e.preventDefault(); | ||
this.navigate(link.getAttribute('href')); | ||
} | ||
}); | ||
} | ||
|
||
handleRoute(pathname) { | ||
const route = this.routes.get(pathname) || this.routes.get('*'); | ||
if (route) { | ||
const app = document.querySelector('#app'); | ||
if (route.layout) { | ||
app.innerHTML = ''; | ||
const layout = new Layout(); | ||
layout.setAttribute('header', route.layout.header); | ||
layout.setAttribute('footer', route.layout.footer); | ||
app.appendChild(layout); | ||
} | ||
|
||
const outlet = RouterOutlet.getInstance(); | ||
if (outlet) { | ||
outlet.innerHTML = ''; | ||
outlet.appendChild(new route.component()); | ||
} | ||
} | ||
} | ||
|
||
navigate(path) { | ||
window.history.pushState({}, '', path); | ||
this.handleRoute(path); | ||
} | ||
|
||
init() { | ||
this.handleRoute(window.location.pathname); | ||
return this; | ||
} | ||
} | ||
|
||
export const router = new Router(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import CanvasPage from '../../features/canvas/pages/CanvasPage'; | ||
|
||
export const routes = { | ||
'*': { | ||
component: CanvasPage, | ||
layout: { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이걸 굳이 따로 config 에 선언해야 하나 싶네요. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 처음에 Route파일에 작성했지만 관심사를 분리하고 싶어서 분리했습니다 |
||
header: 'app-header', | ||
footer: 'app-footer', | ||
}, | ||
}, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
export default class RouterOutlet extends HTMLElement { | ||
static instance = null; | ||
|
||
constructor() { | ||
super(); | ||
|
||
RouterOutlet.instance = this; | ||
} | ||
|
||
connectedCallback() { | ||
this.render(); | ||
} | ||
|
||
render() { | ||
this.innerHTML = ''; | ||
} | ||
|
||
disconnectedCallback() { | ||
RouterOutlet.instance = null; | ||
} | ||
|
||
static getInstance() { | ||
return RouterOutlet.instance; | ||
} | ||
} | ||
|
||
customElements.define('router-outlet', RouterOutlet); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import './ToolButton.js'; | ||
import './PropertyInput.js'; | ||
|
||
export default class CanvasToolsSidebar extends HTMLElement { | ||
connectedCallback() { | ||
this.render(); | ||
} | ||
|
||
render() { | ||
this.innerHTML = ` | ||
<div class="tools-sidebar"> | ||
<div class="property-group"> | ||
<h2 class="section-title">도형</h2> | ||
<tool-button | ||
icon-path="<rect x='3' y='3' width='18' height='18' fill='none' stroke='currentColor' stroke-width='2'/>" | ||
label="사각형"> | ||
</tool-button> | ||
<tool-button | ||
icon-path="<circle cx='12' cy='12' r='9' fill='none' stroke='currentColor' stroke-width='2'/>" | ||
label="원형"> | ||
</tool-button> | ||
<tool-button | ||
icon-path="<line x1='3' y1='12' x2='21' y2='12' stroke='currentColor' stroke-width='2'/>" | ||
label="직선"> | ||
</tool-button> | ||
<tool-button | ||
icon-path="<text x='6' y='16' font-size='14'>T</text>" | ||
label="텍스트"> | ||
</tool-button> | ||
</div> | ||
|
||
<div class="property-group"> | ||
<h2 class="section-title">설정</h2> | ||
<property-input | ||
type="number" | ||
label="가로" | ||
placeholder="Width"> | ||
</property-input> | ||
|
||
<property-input | ||
type="number" | ||
label="세로" | ||
placeholder="Height"> | ||
</property-input> | ||
|
||
<property-input | ||
type="range" | ||
label="투명도" | ||
min="0" | ||
max="100" | ||
value="100"> | ||
</property-input> | ||
</div> | ||
|
||
<button class="reset-button">초기화</button> | ||
</div> | ||
`; | ||
} | ||
} | ||
|
||
customElements.define('canvas-tools-sidebar', CanvasToolsSidebar); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
export default class PropertyInput extends HTMLElement { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 재사용성을 많이 고민하신 듯하네요. 👍 |
||
static get observedAttributes() { | ||
return ['label', 'type', 'placeholder', 'min', 'max', 'value']; | ||
} | ||
|
||
connectedCallback() { | ||
this.render(); | ||
} | ||
|
||
render() { | ||
const label = this.getAttribute('label') || ''; | ||
const type = this.getAttribute('type') || 'text'; | ||
const placeholder = this.getAttribute('placeholder') || ''; | ||
const min = this.getAttribute('min') || 0; | ||
const max = this.getAttribute('max') || 100; | ||
const value = this.getAttribute('value') || 100; | ||
|
||
let inputElement = ``; | ||
|
||
if (type === 'range') { | ||
inputElement = ` | ||
<input | ||
type="range" | ||
class="range-slider" | ||
min="${min}" | ||
max="${max}" | ||
value="${value}" | ||
/> | ||
`; | ||
} else { | ||
inputElement = ` | ||
<input | ||
type="${type}" | ||
class="input-field" | ||
placeholder="${placeholder}" | ||
/> | ||
`; | ||
} | ||
|
||
this.innerHTML = ` | ||
<div class="property-input"> | ||
<label class="input-label">${label}</label> | ||
${inputElement} | ||
</div> | ||
`; | ||
} | ||
} | ||
|
||
customElements.define('property-input', PropertyInput); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
export default class ToolButton extends HTMLElement { | ||
static get observedAttributes() { | ||
return ['icon-path', 'label']; | ||
} | ||
|
||
connectedCallback() { | ||
this.render(); | ||
} | ||
|
||
render() { | ||
const iconPath = this.getAttribute('icon-path') || ''; | ||
const label = this.getAttribute('label') || ''; | ||
|
||
this.innerHTML = ` | ||
<button class="tool-button"> | ||
<svg class="tool-icon" viewBox="0 0 24 24"> | ||
${iconPath} | ||
</svg> | ||
${label} | ||
</button> | ||
`; | ||
} | ||
} | ||
|
||
customElements.define('tool-button', ToolButton); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
index 의 역할은 라우터만 init 해주는 건가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
네 맞습니다 index.js는 시작점으로 라우팅 관련된 코드는 라우팅 파일로 옮겨 응집도를 높혔습니다