티스토리 뷰
오늘은 내가 작성했던 파일을 하나씩 뜯어보는 TIL을 작성해 보고자 한다.
당연히 스스로 만들어낸 기능이 아니므로 뜯어서 공부해 보아야 한다!
간단하게 기능을 설명해 보자면,
영화 상세페이지마다 리뷰를 작성할 수 있고 리뷰 목록은 클릭된 영화에 해당되는 리뷰 목록만 볼 수 있어야 한다.
리뷰를 작성하는 기능은 modal을 이용했으며, 작성된 리뷰는 localstorage에 저장되도록 했다.
HTML과 CSS는 참고할 수 있도록 가장 하단에 작성되어 있으며
html은 새로 알게된 부분만 작성하고, css는 함수가 필요했던 부분만 각 js파일 설명 시 포함해 작성
- HTML id 값을 모두 class component로 만들기 -
우선 html에서 id 값을 모두 class component로 만들었다.
처음에는 id 값을 불러올 때마다 상수로 지정했는데 이름이 겹치니 여간 골치아픈게 아니었다.
그래서 처음 id 값을 불러올때 class component 로 만들자였다.
addEventListener 내에서 class component를 인스턴스화 시켰다.
그리고 DOMContentLoaded 이벤트가 발생하면 class component를 활성화 시킬 수 있다!
거진 모든 내용이 addEventListener( DOMContentLoaded ) 로 진행되기 때문에 다시 한번 간단히 설명하자면
addEventListener
= 특정 이벤트가 발생 했을 때 실행될 함수를 대상 객체에 등록
DOMContentLoaded
= HTML이 완전히 로드되고 파싱되었을때 즉, DOM 구조가 완성되었을 때 발생하는 이벤트이다.
DOMContentLoaded 이벤트가 발생 되면 addEventListener 안에 포함된 여러가지 인스턴스된 class component가 실행
< openModal.js > 리뷰를 작성하기 위한 내용을 담고 있는 모달창
class OpenButton {
constructor(modal) {
this.openButton = document.getElementById("open");
this.modal = modal;
this.addEventListeners();
}
addEventListeners() {
this.openButton.addEventListener("click", (event) => {
this.openModal(event);
});
}
openModal(event) {
event.preventDefault();
this.modal.showModal();
}
}
class Modal {
constructor() {
this.modal = document.getElementById("myModal");
}
showModal() {
this.modal.style.display = "flex";
}
}
document.addEventListener("DOMContentLoaded", function () {
const modalInstance = new Modal();
const openButtonInstance = new OpenButton(modalInstance);
});
OpenButton class, Modal class 만들기
-- class Modal --
class Modal {
constructor() {
this.modal = document.getElementById("myModal");
}
먼저 myModal 요소는 모달창 자체를 말한다.
상속받은 calss가 없음에도 constructor을 사용한 이유!!
① 인스턴스 변수를 초기화하는 로직을 한곳에 모아서 관리
= showModal에서 modal을 가져가서 사용하는데 만약 constrouctor를 이용해 this.modal 변수를 선언하지 않았다면
각각의 매소드에서 this.modal 변수를 계속 선언해서 사용해야 할 것이다.
②인스턴스가 생성될 때마다 동일한 초기화(값 재할당)를 해주므로 재사용성이 높다.
= 하지만 나의경우 modal의 값을 초기화(값 재할당)하지 않았음!
③ DOM 요소에서 한 번만 찾아서 선언해 놓으면 되기 때문에 필요할때마다 새로 찾지 않아도 된다. 성능 최적화
④ modla class안에 매서드들이 this.modal을 사용할 수 있음으로 만약 참조 값을 변경 하고 싶다면 this.modal 만 변경하면 되기 때문에 유지 보수에 좋다.
-- showModal 매서드 --
showModal() {
this.modal.style.display = "flex";
modal을 화면에 고정으로 나타날 수 있도록 해준다.
모달창은 버튼을 클릭할때만 나올 수 있도록 display 값이 none으로 설정되어 있다.
때문에 showModla이 없으면 0.0001초만에 사라지는 것 같다..
-- 새로운 인스턴스 생성 --
document.addEventListener("DOMContentLoaded", function () {
const modalInstance = new Modal();
const openButtonInstance = new OpenButton(modalInstance);
});
DOMContentLoaded 이벤트 리스너 내부에서 Modalclass를 new Modal로 새로운 인스턴스를 생성하여
OpenButton에 생성자를 전달해 modal에 상속받지 않고 파라미터로 받아서 사용할 수 있도록 구현
간단하게 메서드를 사용하기 위해 상속받는 것 대신, 인스턴스를 받아와 사용
➡️재사용성, 모듈성, 각 class의 책임을 명확하게 분리하기에 좋음
**의존성 주입
한 객체가 다른 객체의 의존성을 제공하는 형태. 코드의 재사용성을 높이서 용이성 개선
여기서는 OpenButton이 Modal에 의존성을 제공함(나 너 의존중 니꺼 받아다가 호출좀 할께)
extends(상속) 과는 다름!
=Modal을 상속받아 확장하거나 변경이 필요할 때 적합
-- class OpenButton --
class OpenButton {
constructor(modal) {
this.openButton = document.getElementById("open");
this.modal = modal;
this.addEventListeners();
}
open 이라는 요소는 리뷰작성하기라는 버튼의 id 속성 값이다.
그리고 변수로는 this.openButton, this.modal, this.addEventListeners 총 3개가 있다.
그리고 new Modal, 즉 새로운 인스턴스를 이용해 파라미터로 Modal을 받아왔다.
-- addEventListeners --
addEventListeners() {
this.openButton.addEventListener("click", (event) => {
this.openModal(event);
});
}
변수 this.openButton에 addEventListeners를 사용해 클릭 이벤트가 발생되면 openModal 실행!
-- openModal --
openModal(event) {
event.preventDefault();
this.modal.showModal();
}
openModal 매서드는 전달된 이벤트 메서드를 event.preventDefault 함수로 이벤트의 기본 행동을 취소해 준다.
만약 없었다면 다음 페이지로 자동적으로 이동되었을 것이지만 preventDefault로 다음페이지로 넘어가지 않고
현재 페이지에 머물 수 있도록 해주는 함수이다.
그리고 modal.showModal, 즉 class Modal의 new Modal인 새로운 인스턴스를 받아와
showModal을 호출해 페이지를 지속적을 보여줄 수 있는 상태를 만들었다.
< getStar.js >
class StarRating {
constructor() {
this.stars = document.querySelectorAll(".getstar .star");
this.starIcons = document.querySelectorAll(".getstar .staricon");
this.initialize();
}
initialize() {
this.stars.forEach((star, index) => {
star.addEventListener("change", () => this.updateStars(index));
});
}
updateStars(selectedIndex) {
this.starIcons.forEach((icon, index) => {
if (index <= selectedIndex) {
icon.classList.add("filled");
} else {
icon.classList.remove("filled");
}
});
}
}
document.addEventListener("DOMContentLoaded", function () {
const starRating = new StarRating();
});
getStar.js 는 평점을 줄때 사용될 객체이다.
class StarRating {
constructor() {
this.stars = document.querySelectorAll(".getstar .star");
this.starIcons = document.querySelectorAll(".getstar .staricon");
this.initialize();
}
먼저 getstar 요소는 위에보이는 이미지 전체를 묶고 있는 div가 가지고 있는 class 이름이다.
html에서 1개는 각각 <label> 태그 안에 <input>과 <span> 으로 이루어져 있고 전체는 <div>로 묶여 있다.
<div class="getstar" id="getstar">
<label class="starlabel">
<input class="star" id="star2" type="radio" name="star" value="" />
<span class="staricon"><i class="fa-solid fa-star"></i></span>
</label>
<label class="starlabel">
<input class="star" id="star4" type="radio" name="star" value="" />
<span class="staricon"><i class="fa-solid fa-star"></i></span>
</label>
<label class="starlabel">
<input class="star" id="star6" type="radio" name="star" value="" />
<span class="staricon"><i class="fa-solid fa-star"></i></span>
</label>
<label class="starlabel">
<input class="star" id="star8" type="radio" name="star" value="" />
<span class="staricon"><i class="fa-solid fa-star"></i></span>
</label>
<label class="starlabel">
<input class="star" id="star10" type="radio" name="star" value="" />
<span class="staricon"><i class="fa-solid fa-star"></i></span>
</label>
</div>
그리고
this.stars = document.querySelectorAll(".getstar .star");
this.starIcons = document.querySelectorAll(".getstar .staricon");
document.querySelectorAll 를 이용해 class 이름으로 요소들을 불러왔다.
- querySelectorAll 이용해 class를 사용한 이유!
① 여러 요소에 동일하게 적용이 되어야 한다.
② <div class="getstar"></div> 로 묶인 star를 전부 사용해야 한다.
= querySelectorAll 를 이용해 class를 불로 오는 경우 자식요소를 선택할 수 있다.\
③ id로 불러오기 위해서는 모두 개별적으로 가져와 개별적으로 동일한 코드를 여러번 작성해야 한다.
id를 사용할 수 없는 이유!
① id의 고유성으로 인해 한개의 요소에만 적용이 된다.
② id를 선택하는 경우 자식요소를 선택할 수 없다
this.initialize();
initialize 매서드 호출
initialize() {
this.stars.forEach((star, index) => {
star.addEventListener("change", () => this.updateStars(index));
});
}
initialize는 getstar.star에 star과 index 값을 받아 star에 change가 발생 되면 updateStarts(인덱스값) 매서드 호출
updateStars(selectedIndex) {
this.starIcons.forEach((icon, index) => {
if (index <= selectedIndex) {
icon.classList.add("filled");
} else {
icon.classList.remove("filled");
}
});
}
}
updateStars는
starIcons에 icon, 인덱스 값을 인자로 받아 selectedIndex 와 인덱스의 값이 작거나 같으면 icon을 채워주고
그게 아니라면 비워준다.
즉 선택된 인덱스의 값만큼 별을 채워주고 선택되지 않았다면 별을 채우지 않도록 작성!
'TIL' 카테고리의 다른 글
2024. 01 .17 TMDB 영화 리뷰 기능 구현 코드 뜯어보기_3 (팀프로젝트) (0) | 2024.01.17 |
---|---|
2024. 01 .16 TMDB 영화 리뷰 기능 구현 코드 뜯어보기_2 (팀프로젝트) (0) | 2024.01.16 |
2024. 01. 14 팀 프로젝트 완료 & Git push (0) | 2024.01.14 |
2024.01.13 프로젝트 마지막 단계. 코드 합치기 (2) | 2024.01.13 |
2024.01.11 팀 프로젝트 2 (0) | 2024.01.11 |
- Total
- Today
- Yesterday
- axios 사용하기
- 유효성검사 css
- styled component 사용방법
- readme작성해보기
- 유효성검사
- 별점만들기
- git cache
- axiosinstance 사용 시 토큰 사용 법
- axios 설치하기
- 영화 별점
- readme 작성해야 하는 이유
- 에러모음집
- Fetch와 Axios 의 장단점
- styled component 조건부 사용방법
- styled component 설치방법
- nextjs 토큰 만료처리하기
- Warning: validateDOMNesting(...): <li> cannot appear as a descendant of <li>
- simple Icon 사용방법
- readme 역할
- readme 이미지 추가 방법
- 별점 색채우기
- axios CRUD
- readme 작성 방법
- 영화별점만들기
- styled component GlobalStyle 사용방법
- axios instance 작성하기
- Warning: A component is changing an uncontrolled input to be controlled.
- Warning: Each child in a list should have a unique "key" prop.
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |