Skip to content

[10기 이누렁] TodoList with CRUD #212

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

Open
wants to merge 11 commits into
base: inust33
Choose a base branch
from

Conversation

nerdyinu
Copy link

@nerdyinu nerdyinu commented Jul 12, 2021

  • 우선 요구하는 기능을 수행하기 위해 class가 필요하다고 생각하여 전체적으로 class로 component들을 구성하였습니다.

  • 생성자 함수를 활용하는 것이 더 좋아보이는데, 저의 이해가 부족한 까닭으로 class를 활용하여 진행하였습니다. 객체와 생성자 함수에 대한 공부를 조금 더 해야할 것 같습니다.

  • 전체적인 구성은 JunilHwang님의 https://junilhwang.github.io/TIL/Javascript/Design/Vanilla-JS-Component/ 이 글을 많이 참고하였습니다. 다른 분들도 한 번씩 읽어보시면 좋을 것 같아요!

  • mounted에서 하위 컴포넌트 객체를 생성하고, props로 필요한 기능 및 state 등을 넘겨주는 형식으로 진행하였습니다. core에 뼈대가 되는 component를 만들고, 하위 컴포넌트들은 components 파일에 분리하였습니다.

  • 이 과정에서 함수 바인딩의 필요성도 공부할 수 있었습니다.

  • state은 필터링 상태를 나타내는 isFilter, 현재 수정하기 모드로 선택된 todoItems를 나타내는 selectedItem과 todoItems의 배열로 구성되어 있습니다.

  • event "dblclick"을 label 태그에 등록하고, 이벤트 발생 시

  • 태그의 클래스명에 editing을 추가하는 것까진 구현하였는데, 미션에 안내된대로 수정 input이 나타나지 않아서 뭐가 문제인지 봐주시면 감사하겠습니다. html상에서 li의 class에 editing을 추가하는 것 외에 더 구현해야할 부분이 있는지 궁금합니다. - 해결됐습니다! 감사합니다 태그의 위치가 변경되어 있었네요...

Copy link

@ink-0 ink-0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제가 Class 형으로 구현하지 않았는데, 잘 정리되어 있어서 좋았습니다.
생성자 함수를 활용함에 있어 어려움을 느끼셨다고 했는데, 프로그래머스 고양이사진첩 웹기출 해설 한번 읽어보시는 것 추천드릴게요 🥰

코드가 간결하고 메서드 네임에 규칙이 있어서 많이 배울 수 있었습니다.
다음 미션도 화이팅 하세요

Comment on lines +22 to +29
setEvent() {
const { filterItem } = this.$props;
this.addEvent("click", ".filter", (event) => {

filterItem(Number(event.target.dataset.filter));
});
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dataset으로 DOM프로퍼티에 접근하는 방식 정말 간편하네요 !

Comment on lines 10 to 19
${filteredItems.map(({ id, content, isComplete }) => `
<li class="${isComplete ? "completed" :'false'} ${selectedItem===id?"editing":""}" data-id="${id}">
<div class="view">
<input class="toggle" type="checkbox" ${isComplete? "checked" : ''}/>
<label class="label">${content}</label>
<button class="destroy"></button>
<input class="edit" value=""/>
</div>
</li>`).join(``)}`
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

완료상태, 편집상태 를 조건으로 추가해주셨군요! 좋은 방법이네요!
지금까지 봐서는 html 상에서 editing 외에 추가할 것이 필요해 보이진 않네요.!

Comment on lines +24 to +32
this.addEvent("click", ".destroy", ({ target }) => {
deleteItem(Number(target.closest(`[data-id]`).dataset.id))
});
this.addEvent("dblclick", ".label", (event) => {
editItem(Number(event.target.closest(`[data-id]`).dataset.id));
});
this.addEvent("input", ".toggle", ({ target }) => {
toggleItem(Number(target.closest(`[data-id]`).dataset.id));
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이벤트 가독성이 매우 좋아요❤️

Comment on lines +4 to +8
export function checklength(item) {
if (item.length === 0) {
return alert("아이템 내용을 입력해주세요");
} else {}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

헉. 사용자 에러 처리까지.. 멋집니다..

Comment on lines +73 to +103
addItem(content) {
const { todoItems } = this.$state;
const id = Math.max(0, ...todoItems.map(v => v.id)) + 1;
const isComplete = false;
this.setState({
todoItems: [
...todoItems,
{ id, content, isComplete }
]
});
}
updateItem(contents) {
const { todoItems, selectedItem } = this.$state;
todoItems[selectedItem].content = contents;
this.setState({ todoItems, selectedItem: -1 })
}

editItem(id) {
this.setState({ selectedItem: id });
}
toggleItem(id) {
const { todoItems } = this.$state;
const key = todoItems.findIndex(item => item.id === id);
todoItems[key].isComplete = !todoItems[key].isComplete
this.setState({ todoItems });
}
deleteItem(id) {
const { todoItems } = this.$state;
todoItems.splice(todoItems.findIndex(item => item.id === id), 1);
this.setState({ todoItems });
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

메서드가 한번에 정리되어 있어서 로직이 한번에 이해됩니다 . 너무 좋습니다!

Copy link

@jeleedev jeleedev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

안녕하세요. 이지은입니다
코드가 너무 깔끔하게 잘 작성 돼있어서 많이 배우고 갑니다 👍
수고하셨습니다 :)

new TodoContainer($todoCount, { //todocount와 filter를 가지는 컨테이너
itemCount: todoItems.length,
filterItem: filterItem.bind(this)
});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bind를 사용해서 이렇게 구현할 수 도 있군요. 코드가 정말 깔끔하네요 👍


addItem(content) {
const { todoItems } = this.$state;
const id = Math.max(0, ...todoItems.map(v => v.id)) + 1;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오홉.. todoItems.length 를 사용하지 않고 Math.max() 를 사용한 이유가 있을까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오홉.. todoItems.length 를 사용하지 않고 Math.max() 를 사용한 이유가 있을까요?

length로 하게되면 중간에 위치한 id를 지웠을 경우 중복값이 존재할 수 있습니다!

<input class="toggle" type="checkbox" ${isComplete? "checked" : ''}/>
<label class="label">${content}</label>
<button class="destroy"></button>
<input class="edit" value=""/>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<input class="edit" value=""/>
value${content}가 빠진거 아닐까요?

},
"homepage": "https://github.com/inust33/js-todo-list-step1#readme",
"devDependencies": {
"webpack": "^5.44.0",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

webpack을 추가적으로 사용하신 이유가 무엇인가요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

따로 이유가 있는 것은 아니구, 바벨 플러그인을 이용하여 jsx나 리액트 컴포넌트를 구현할 수 있다고 하길래 시도해보려 하였으나 그만두었습니다!


setup() {
this.$state = {
todoItems: [

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

초기 default 상태를 외부에서 주입하는 것도 좋을꺼 같네요. 데이터와 구조는 분리되어야 확장성이 생기니까요.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

조언 감사합니다! 말씀하신대로 외부에서 주입하려면 setup()함수를 아예 외부로 빼는거라고 생각하면 될까요?

<li>
<a class="filter" href="#completed" data-filter="1">완료한 일</a>
</li>
</ul>`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

view가 가장 먼저 보이는 방식 좋네요:)

}
],
selectedItem: -1,
isFilter: 0

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0,1,2 보다 문자로 표시하는것이 더 이해하기 쉬울꺼 같습니다.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

참고하겠습니다.

this.render();

}
addEvent(eventType, selector, callback) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

state가 바뀔때마다 event가 새로 등록되는데 상위 노드에서 정적인 요소에 이벤트를 등록해도 좋을꺼 같습니다.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setevent는 constructor로 생성시에만 등록되고, 렌더함수 실행시에는 다시 등록되지 않도록 코딩하였는데, 혹시 어떤 부분에서 새로 등록된다고 보신건가요?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants