-
Notifications
You must be signed in to change notification settings - Fork 217
[10기 이재훈] ToDoList CRUD #213
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
base: main
Are you sure you want to change the base?
Changes from all commits
3e5c577
3d523dd
086f6ad
214419e
08a6ee4
3edd007
980c439
915fc8c
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,18 @@ | ||
import { ToDoInput,ToDoList } from "./component/index.js"; | ||
class App { | ||
$todoInput; | ||
$todoList; | ||
constructor(){ | ||
const toDoInputTarget = document.querySelector("#new-todo-title"); | ||
const toDoListTarget = document.querySelector('#todo-list'); | ||
this.$todoInput = new ToDoInput(toDoInputTarget,{ | ||
addToDoItem: itemTitle => this.addToDoItem(itemTitle) | ||
}); | ||
this.$todoList = new ToDoList(toDoListTarget); | ||
} | ||
addToDoItem(itemTitle){ | ||
this.$todoList.addItem(itemTitle); | ||
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. todoList와 todoInput이 강하게 묶여 있습니다. observer 패턴형태를 참고해서 수정해도 좋을꺼 같습니다. 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. 넵넵 todoList 와 todoInput을 상위에서 묶음으로써 todoList 컴포넌트와 todoInput 컴포넌트의 state를 따로 관리하였고, 그로인해서 state 초기화가 달랐던것입니다! observer 패턴을 잘 모르지만 공부해서 반영해보도록 하겠습니다! |
||
} | ||
} | ||
|
||
const app = new App(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
export class ToDoInput { | ||
state; | ||
$target; | ||
props; | ||
constructor(target,props){ | ||
this.$target = target; | ||
this.props = props; | ||
this.state = { | ||
toDoItem : "" | ||
} | ||
this.initEventListener(); | ||
} | ||
|
||
render () { | ||
|
||
} | ||
|
||
initEventListener () { | ||
this.$target.addEventListener('input',({target})=>{ | ||
this.setState({toDoItem: target.value}) | ||
}) | ||
this.$target.addEventListener('keydown',({key})=>{ | ||
if(key === "Enter") { | ||
this.props.addToDoItem(this.state.toDoItem); | ||
this.reset(); | ||
}; | ||
}) | ||
} | ||
|
||
setState (payload) { | ||
this.state={...this.state,...payload} | ||
} | ||
reset(){ | ||
this.setState({toDoItem:""}); | ||
this.$target.value = ""; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { TODO_STATE } from "../constant/index.js"; | ||
const getStateClass = (state) => { | ||
return state === TODO_STATE.COMPLETED ? 'class="completed"' : | ||
state === TODO_STATE.EDITING ? 'class="editing"' : | ||
''; | ||
} | ||
export class ToDoList { | ||
state; | ||
$target; | ||
constructor(target){ | ||
this.$target = target; | ||
this.setState({ | ||
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. state를 초기화하는 방식이 TodoInput과 다릅니다. |
||
items:[] | ||
}) | ||
} | ||
render(){ | ||
const {items} = this.state; | ||
this.$target.innerHTML = items.map(({state,title})=>` | ||
<li ${ getStateClass(state) }> | ||
<div class="view"> | ||
<input class="toggle" type="checkbox" ${state === TODO_STATE.COMPLETED ? 'checked' : '' }/> | ||
<label class="label">${title}</label> | ||
<button class="destroy"></button> | ||
</div> | ||
${ state === TODO_STATE.EDITING ? `<input class="edit" value="${title}" />` : '' } | ||
</li> | ||
`).join('') | ||
|
||
} | ||
initEventListener(){ | ||
this.addToggleEvent(); | ||
this.removeToggleEvent(); | ||
|
||
} | ||
|
||
addToggleEvent(){ | ||
const toggleComponents = this.$target.querySelectorAll('.toggle'); | ||
const {items} = this.state; | ||
toggleComponents.forEach((element,idx) => { | ||
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. 모든 토글에 리스너를 등록하는 방법 대신 이벤트위임을 통해 부모 노드에만 이벤트를 등록하는 방법을 고려해보세요. |
||
element.addEventListener('change',(({target})=>{ | ||
const todoItem = items[idx]; | ||
todoItem.state = target.checked ? TODO_STATE.COMPLETED : TODO_STATE.TODO | ||
items[idx] = {...todoItem}; | ||
this.setState({items:[...items]}); | ||
}) | ||
)}); | ||
} | ||
|
||
removeToggleEvent(){ | ||
const destroyComponents = this.$target.querySelectorAll('.destroy'); | ||
const {items} = this.state; | ||
destroyComponents.forEach((element,idx)=>{ | ||
element.addEventListener('click',()=>{ | ||
items.splice(idx,1); | ||
this.setState({items:[...items]}) | ||
}) | ||
}) | ||
} | ||
|
||
setState(payload){ | ||
this.state = {...this.state, ...payload}; | ||
this.render(); | ||
this.initEventListener(); | ||
} | ||
addItem(itemTitle){ | ||
this.setState({ | ||
items: [...this.state.items, | ||
{ | ||
title:itemTitle, state: TODO_STATE.TODO | ||
}] | ||
}) | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export {ToDoList} from "./ToDoList.js" | ||
export {ToDoInput} from "./ToDoInput.js" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export const TODO_STATE = { | ||
TODO: 0, | ||
COMPLETED: 1, | ||
EDITING: 2, | ||
} |
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.
반복되는 document.querySelector를 유틸함수로 빼서 재사용해보는것도 좋을꺼 같아요.