소개
강의
수강평
- 문법 공부 다음엔, 자바스크립트 프로젝트 101
- 자바스크립트 ES6+ 기초 핵심 문법
- 문법 공부 다음엔, 자바스크립트 프로젝트 101
게시글
질문&답변
쌤 에러가 계속 나요ㅠㅠ
안녕하세요 모짜르트님.보니까 데이터는 products.json 이고 불러오려는 것은 product.json (s가 빠짐)인 것 같습니다. 또한 asssert 대신 with 를 넣어 아래 코드 테스트로 사용하시길 바랍니다~ with 에 대한 내용은 여기를 참고해주세용import products from '../products.json' with { type: 'json' }; console.log(products.data);
- 0
- 2
- 37
질문&답변
bmi 계산기 질문있습니다.
안녕하세요.display 함수 안에서 왜 group 변수를 초기화 하지 않고 변수만 선언한 이유는 (물론 안전하게 공백 등으로 초기화를 해줘도 좋지만) 변수에 들어갈 값이 바로 아래에서 결정되기 때문입니다.설명은 아래 주석을 참고해주세요! const display = (bmi) => { const result = document.querySelector('.result'); // 여기서 선언된 result는 const 상수이므로 반드시 우리가 사용하려는 객체로 초기화가 되어야 합니다. const 상수는 선언과 동시에 초기화가 이루어져야 하고, 값이 변경되지 않습니다. // 특별한 이유 = 값이 중간에 변경 되거나 확실하지 않은 어쩔 수 없는 경우를 제외하고는, 자바스크립트는 const를 기본으로 사용하시는 것이 좋습니다. let group; // 여기서 group 변수는 선언만 되고 초기화 되지 않았습니다. // 바로 아래 if 안에 걸리는 구간에서 값이 할당됩니다. // 왜 if 안에서 선언하면 안되느냐? = 각각의 변수가 아닌 하나의 변수를 사용하기 위해서 밖에서 선언한 것입니다. // 왜 애초에 위에서 초기화 하지 않느냐? = 여기 선 값을 결정하지 못했기 때문입니다. 해당 예제가 간단한 예제라서 이렇게 한 바닥에 다 보이게끔 작성을 했는데요. 꼭 이렇게만 해야 한다는 법칙 같은 것은 없으며, 만약 이 구조가 싫다면 값을 결정하는 구간을 선행하게끔 로직을 변경하시면 됩니다! (예 : 텍스트를 반환하는 함수를 따로 만들어서, display 함수에서는 업데이트만 해준다) if (bmi >= 30.0) { group = '중등도비만'; } else if (bmi >= 25.0) { group = '경도비만'; } else if (bmi >= 23.0) { group = '과체중'; } else if (bmi >= 18.5) { group = '정상'; } else { group = '저체중'; } result.innerText = `${bmi} → ${group} 입니다.`; }; 다음 링크를 함께 참고해보시면 더 좋을 것 같습니다.https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/const
- 0
- 2
- 36
질문&답변
flexbox와 grid
레이아웃을 짜는데 정답은 없습니다! 그리드든 플렉스는 애초에 어떤 구성을 기획하셨는지가 제일 중요해요. 그 모양으로 만들 수 있다면 그리드를 썼다고 틀린 것은 아닙니다. 또한 모바일에 대한 반응형 처리를 어떻게 할지에 따라 달라질 수 있습니다. 위와 같은 디자인은 전부 플렉스로 잡아도 충분할 것 같습니다 ^^한 마디로 그리드든 플렉스는 2개 다 반드시 잘 알고 계셔야 하고, 어떤 걸 쓰더라도 본인이 생각한 레이아웃을 잡을 수 있으면 되기 때문에 어떤 식으로 레이아웃을 잡아야 하는지 다양한 옵션에 대한 이해가 기본 되어야 합니다. 다만 추천을 드리자면, 그냥 가로든 세로든 쌓여 있기만 하면 된다면 플렉스를, 조금 독특한 구조의 레이아웃을 구성해야 하거나, 완전 표 형식의 규칙적인 데이터를 다룰 때는 그리드를 사용하시면 더 좋습니다.
- 0
- 2
- 301
질문&답변
#21 그리드 강의 정렬 관련 속성
작성하신 코드의 상속 관계를 정확히 보여주시면 더 정확한 답변 드릴 수 있을 것 같습니다~
- 0
- 2
- 208
질문&답변
재밌게 잘 듣고있어요~
safeArea님 안녕하세요.네 학습 순서는 괜찮은 것 같습니다. 다만 자바스크립트로 개발 경험이 많지 않으시다면, 딥다이브 강의가 조금 어려울 순 있을 것 같습니다만, 워낙 좋은 강의이니 딥다이브 책과 강의는 교양처럼 개발하시면서 공부하셔도 좋을 것 같아요~ 최종적으로 리액트로 포폴을 만들고 싶으신거라면, 이 강의 들으시고 난 다음 리액트 강의를 기초부터 다양하게 들어보시면 더 좋을 것 같습니다. ^^그리고 ES는 자바스크립트 표준 규격이고, 크롬은 자바스크립트를 포함하고 있기 때문에 작동은 걱정하지 않으셔도 됩니다~https://www.w3schools.com/js/js_versions.asphttps://caniuse.com/
- 0
- 1
- 188
질문&답변
bmi 계산기 css가 적용이 안됩니다
안녕하세요 지만님.해당 오류는 경로가 잘못 되었을 경우 발생합니다. 작업 중인 폴더 /common/reset.css 경로에 해당 파일이 존재하는지 확인해보시고, 만약 공용으로 사용하는 파일을 추가하지 않으셨다면 추가해주시면 됩니다.https://github.com/erumcoding/js-project-101/tree/main/common
- 0
- 1
- 265
질문&답변
trello-app에서 질문 있습니다
duswlskfk42님 안녕하세요. 먼저, dragOver에서 말하는 타겟이란, 드래그-오버 되고 있는 대상을 의미하는데요. 이 이벤트는 이벤트 리스너가 달려있는 블록에서 드래그가 이루어지면 발생합니다. (현재 각각 todo, doing, done 리스트 블록)또한 listIds는 애초 리스트의 이름 (아이디)를 뽑아내기 위해 Object.keys를 사용해 가져오는 것이므로, todo, doing, done만 나오는 것이 맞습니다. 결론적으로, 할 일을 드래그 해서, listIds 값 중 하나와 동일한 아이디를 가진 블록 위로 드래그 한다면, to에 해당 리스트의 아이디 값을 대입해 도착지를 그곳으로 설정하게 되고, 드래그가 끝난 시점에 출발지와 도착지가 다른 경우에만 dragEnd 함수의 동작을 통해 요소가 이동 (실제로는 출발지에서 삭제 후 도착지에서 새롭게 생성)하게 됩니다.즉, 올바르게 블록 단위로 드래그 되어 타겟 아이디가 리스트 블록의 아이디 중 하나를 갖지 않는다면, uuid는 당연히 listIds에 없기 때문에 이동하지 않습니다. 그래서 반드시 다른 블록 (이벤트 리스너가 달려 있는 리스트 블록) 안에 놓아야만 이동하는 것으로 구현이 됩니다. 다음 코드를 테스트 해보시면 좋을 것 같습니다.const dragOver = (event) => { event.preventDefault(); const { id: targetId } = event.target; const listIds = Object.keys(lists); console.log(event.currentTarget.id); if (listIds.includes(targetId)) { to = targetId; } }; 만약 왜 내부 할 일 항목에서도 이벤트가 발생하는 것처럼 보이는지 이 부분을 더 자세히 알고 싶으시다면, 자바스크립트의 이벤트 전파 방식 부분, Event Target과 Current Target의 차이점 등을 함께 공부하시면 도움이 될 것 같습니다.
- 0
- 1
- 263
질문&답변
깃허브 자료에 bmi 계산기 문의
안녕하세요 그레이룩쇼님!파일 정상임을 확인했습니다. index.html 파일 상단에 다음과 같이 2개의 스타일시트 관련 코드가 있습니다. 참고로 common 파일은 공통으로 쓰는 부분입니다!확인 결과(사진)링크https://github.com/erumcoding/js-project-101/tree/main/commonhttps://github.com/erumcoding/js-project-101/blob/main/01-exercise/03-bmi-cal/style.css
- 0
- 1
- 248
질문&답변
해결되지않는 부분이 있어서 질문드려요
다른 글에 답변 드렸습니다.혹시 같은 문제가 있으신 분들은 해당 글을 참고해주세요!https://www.inflearn.com/questions/1041836
- 0
- 3
- 233
질문&답변
아 네~다시 질문드립니다.
우선, init() 함수에서 만약 로컬스토리지에 저장된 todos가 있다면 그것을 파싱 해오는데, 그것을 페이지 내에서 조작하기 위해서 사용하는 글로벌 변수 todos에 넣는 과정이 없습니다. 그렇기 때문에 로컬스토리지에는 있고, 글로벌 변수에는 없어서, 마치 제대로 저장되고 복원 되는 것처럼 보이지만, 조작하면 (조작하는 대상은 글로벌 변수 todos 이므로) 문제가 생기게 됩니다. // 페이지 내에서 조작하는 todos는 글로벌 변수인 todos 입니다. let todos = []; const init = () => { // 이 친구는 어디로? const userTodos = JSON.parse(localStorage.getItem('todos')); if (userTodos) { userTodos.forEach((todo) => { addItem(todo); }); // 아래 부분을 추가해 주어야 합니다. todos = userTodos; } }; 또한 init() 함수에서 로컬스토리지에 저장된 항목이 있음에도 불구하고 todoCount.textContent를 0으로 초기화 하고 있습니다. 추측컨데, 이 기능이 올바르게 작동하려면 0으로 초기화 하는 것이 아니라, 저장된 개수를 세서 넣어줘야 할 것으로 보입니다. const init = () => { const userTodos = JSON.parse(localStorage.getItem('todos')); if (userTodos) { userTodos.forEach((todo) => { addItem(todo); }); todos = userTodos; // 다음과 같이 수정되어야 합니다. updateTodoCount(); } }; 추가로, 더 정확히는, 이 기능은 저장된 배열이 있던 없던 저장된 항목의 개수를 세어 표기하는 기능으로 보이기 때문에, 다음과 같이 if문 밖에 작성되어야 할 것 같습니다. 그래야 저장된 항목이 없어도 0 task 라고 표기됩니다. const init = () => { const userTodos = JSON.parse(localStorage.getItem('todos')); if (userTodos) { userTodos.forEach((todo) => { addItem(todo); }); todos = userTodos; } updateTodoCount(); }; 세 번째로, 전체 삭제 함수에서 임의로 테스크 개수를 0이라고 덮어씌울 필요없이, 이미 글로벌 변수 todos의 모든 내용을 지웠기 때문에 그냥 개수를 세는 함수를 호출하시면 됩니다. clearAll.addEventListener('click', () => { ul.innerHTML = ''; todos = []; localStorage.removeItem('todos'); updateTodoCount(); }); 네 번째로, 이미 이벤트 핸들러에서 input.value !== ''임을 체크하고 공백이 아닌 것들만 addItem() 함수를 실행하고 있기 때문에, 중복으로 검증하실 필요는 없습니다. 따라서 if문을 핸들러 안에 두신다면 다음과 같이 수정하셔도 됩니다. const addItem = (todo) => { const li = document.createElement('li'); const span = document.createElement('span'); const icon = document.createElement('i'); d icon.classList.add('fa-solid', 'fa-trash-can'); span.innerText = todo.text; icon.addEventListener('click', delItem); ul.appendChild(li); li.appendChild(span); li.appendChild(icon); li.id = todo.id; updateTodoCount(); }; 수정된 전체 코드const form = document.querySelector('form'); const input = document.querySelector('input'); const ul = document.querySelector('ul'); const todoCount = document.querySelector('.todo-count'); const clearAll = document.querySelector('.clear-all'); let todos = []; const save = () => { localStorage.setItem('todos', JSON.stringify(todos)); }; const updateTodoCount = () => { todoCount.textContent = todos.length; }; const clearItems = () => { ul.innerHTML = ''; todos = []; localStorage.removeItem('todos'); updateTodoCount(); }; const delItem = (event) => { const target = event.target.parentElement; todos = todos.filter((todo) => todo.id !== parseInt(target.id)); save(); target.remove(); updateTodoCount(); }; const addItem = (todo) => { const li = document.createElement('li'); const span = document.createElement('span'); const icon = document.createElement('i'); icon.classList.add('fa-solid', 'fa-trash-can'); span.innerText = todo.text; icon.addEventListener('click', delItem); ul.appendChild(li); li.appendChild(span); li.appendChild(icon); li.id = todo.id; updateTodoCount(); }; const handler = (event) => { event.preventDefault(); const todo = { id: Date.now(), text: input.value, }; if (input.value !== '') { todos.push(todo); addItem(todo); save(); input.value = ''; } }; const init = () => { const userTodos = JSON.parse(localStorage.getItem('todos')); if (userTodos) { userTodos.forEach((todo) => addItem(todo)); todos = userTodos; } updateTodoCount(); }; init(); form.addEventListener('submit', handler); clearAll.addEventListener('click', clearItems);
- 0
- 1
- 192