[TS 과제 챌린지] Movie Seat Booking - 트러블슈팅

조민호·2023년 5월 17일
0


로컬스토리지 사용시 주의사항

로컬스토리지 특성상 getItem을 사용했을 때 , 해당 값이 리턴되거나

null값이 리턴될 수도 있습니다

이 말은, 반드시 null처리를 따로 진행해줘야 한다는 것입니다

let localStorageResult : string|null= localStorage.getItem('selectedSeats');

이 방식대로 union type으로 막는 것은 불가능하며

  • non-null assertion을 사용하던가
    const initialSetting = () => {
    
    	**// non-null assertion 사용**
      let localStorageResult = 
    			localStorage.getItem('selectedSeats')!;
    
    	// null이 아닐 경우 마저 로직 진행
      let selected: number[] = JSON.parse(localStorageResult);
    	...
    };
  • 따로 null에 대한 로직처리를 진행해줘야 합니다
    const initialSetting = () => {
    
      let localStorageResult = localStorage.getItem('selectedSeats');
    
    	**// null 처리**
      if (localStorageResult === null) {
        throw new Error('null');
      }
    
    	// null이 아닐 경우 마저 로직 진행
      let selected: number[] = JSON.parse(localStorageResult);
    	...
    };



classList 사용하기

classList는 JavaScript에서 요소의 클래스를 조작하는 데 사용되는 유용한 기능이며 클래스 이름을 추가, 제거 및 토글할 수 있습니다

<div id="myDiv" class="class1 class2"></div>
// 요소 가져오기
let myDiv = document.getElementById('myDiv');

// 클래스 목록 가져오기
let classList = myDiv.classList;

console.log(classList);
// DOMTokenList(2) ['class1', 'class2', value: 'class1 class2']
console.log(classList[0]); // class1
console.log(classList[1]); // class2

classList는 element의 읽기전용 속성으로 ( 00.classList = value가 안됨)

class에 지정된 값들을 반환합니다

그렇지만 , classList의 반환값은 DOMTokenList 객체 이므로

element의 class 속성을 보여주면서 classList가 읽기전용이어도 다양한

메소드를 통해 class 목록을 조작할 수 있습니다

그렇다면 DomTokenList의 메서드에 대해 알아봅시다


  • Element.classList.toggle 토글은 !연산자를 통해 false와 true를 왔다갔다 하는 것처럼 반복되는 행위를 의미합니다 즉, 기존 값이 0이었다면 1로 바뀌고 기존 값이 1이었다면, 0으로 바뀌게 됩니다. toggle() 메서드는 해당 요소에 클래스가 존재한다면 클래스를 제거하고, 클래스가 존재하지 않는다면 해당 요소에 클래스를 추가하는 메서드입니다
    <div id="myDiv" class="class1 class2"></div>
    // 요소 가져오기
    let myDiv = document.getElementById('myDiv');
    
    // 클래스 목록 가져오기
    let classList = myDiv.classList;
    
    // class2를 삭제하고 class3를 추가합니다
    classList.toggle('class2');
    classList.toggle('class3');
    
    console.log(classList);
    // DOMTokenList(2) ['class1', 'class3', value: 'class1 class3']
  • Element.classList.add 명시된 클래스를 추가하는 메서드입니다.
    <div id="myDiv" class="class1 class2"></div>
    // 요소 가져오기
    let myDiv = document.getElementById('myDiv');
    
    // 클래스 목록 가져오기
    let classList = myDiv.classList;
    
    // class3를 추가합니다
    classList.add('class3');
    
    console.log(classList);
    // DOMTokenList(3) ['class1', 'class2', 'class3', value: 'class1 class2 class3']
  • Element.classList.remove 명시된 클래스를 제거하는 메서드입니다.
    <div id="myDiv" class="class1 class2"></div>
    // 요소 가져오기
    let myDiv = document.getElementById('myDiv');
    
    // 클래스 목록 가져오기
    let classList = myDiv.classList;
    
    // class3를 삭제합니다
    classList.remove('class2');
    
    console.log(classList);
    // DOMTokenList ['class1', value: 'class1']
  • Element.classList.replace 기존에 존재하는 클래스를 명시한 클래스로 교체하는 메서드입니다
    <div id="myDiv" class="class1 class2"></div>
    // 요소 가져오기
    let myDiv = document.getElementById('myDiv');
    
    // 클래스 목록 가져오기
    let classList = myDiv.classList;
    
    // class1을 class10으로 변경합니다
    classList.replace('class1', 'class10');
    
    console.log(classList);
    // DOMTokenList(2) ['class10', 'class2', value: 'class10 class2']
  • Element.classList.contains 클래스가 존재하는지 확인하는 메서드 입니다
    <div id="myDiv" class="class1 class2"></div>
    // 요소 가져오기
    let myDiv = document.getElementById('myDiv');
    
    // 클래스 목록 가져오기
    let classList = myDiv.classList;
    
    // class1을 가지고 있는지 확인합니다
    let result = classList.contains('class1');
    
    console.log(result); // true

classList를 사용하면 클래스 이름을 직접 조작하는 것보다 더 편리하고 안전합니다.

특히 CSS 스타일을 동적으로 조작하는 데 유용합니다




Event 타입 지정

TS로 이벤트 리스너를 할당할때 ,

  • 해당 요소가 클릭됐을 때 이벤트가 발생한 정확한 위치를 굳이 참조할 필요 없이 일정한 로직만 진행하게 된다면 addEventListener의 두번째 인자로 함수만 전달해 주면 됩니다 ex) 버튼클릭하면 일정한 동작만 진행
    playButton.addEventListener('click', playOrStop);
    // 재생 버튼을 누르면 비디오가 재생중이면 일시정지
    // 일시정지라면 재생
    
    const video = document.getElementById('video');
    // 일시 정지 , 재생을 다루는 함수
    const playOrStop= () => {
    
     // 재생중일 때
     if (video.paused) video.play()
    
     //일시정지 or 정지일 때
     if (!video.paused) video.pause();
      
    };
  • 그렇지만 이벤트가 발생한 곳을 정확히 참조해야 하고 이걸 기반으로 이벤트를 진행해야 한다면 e.target을 사용합니다
    <form id="form">
    	FORM
    		<div>
    			DIV
    			<p>P</p>
    		</div>
    </form>
    
    form.onclick = function (event) {
    		event.target.style.backgroundColor = 'yellow';
    };

두번째의 경우, e의 타입을 지정해 줘야 하는데

Elment와 HTMLElemnt의 위계가 존재하는 것처럼, Event에도 상속관계가 존재합니다

Event > UIEvent > MouseEvent, TouchEvent, FocusEvent, KeyboardEvent, InputEvent 등

그러므로 event를 사용할때는 타입으로 Event타입을 지정해줘야 합니다

container.addEventListener('click', (e: **Event**) => {
  if (!(e.target as HTMLDivElement).classList.contains('occupied')) {
    (e.target as HTMLDivElement).classList.toggle('selected');
    updateSeats();
  }
});



select 태그에서 선택된 값과 인덱스 알아내기

<select class="selectTest">
    <option name="test1" selected="selected">Test1</option>
    <option name="test2">Test2</option>
    <option name="test3">Test3</option>
</select>
  • 선택된 option 태그에 적용된 값을 알려면 .value 프로퍼티를 사용하며

  • select 에서 선택된 option의 인덱스를 알기 위해선

    .selectedIndex 프로퍼티를 사용합니다



let test = document.getElementsByClassName("selectTest");
// test 변수에 selectTest란 클래스명을 가진 요소를 저장

let indexNo = test[0].selectedIndex;
// test 변수의 선택된 값을 indexNo에 저장

console.log(indexNo); // 0



div 요소 위치 가져오기

div요소가 여러개 있을 때, 특정 클래스가 있는 인덱스를 알기 위해선

굳이 어렵게 생각할 필요 없이 배열개념으로 진행하면 됩니다

즉 ,배열로 변환을 한 후에 indexOf를 사용하면 됩니다

상위 요소인 row클래스 안에 존해하는 div 중에서

selected클래스가 존재하는 div클래스의 인덱스를 출력합니다

<div class="row">
        <div class="seat"></div>
        <div class="seat"></div>
        <div class="seat selected"></div>
        <div class="seat selected"></div>
        <div class="seat"></div>
        <div class="seat"></div>
        <div class="seat"></div>
        <div class="seat"></div>
</div>
		
	const seats = document.querySelectorAll('.row .seat') as NodeListOf<HTMLElement>;

	// selected된 div를 모두 가져옴
	const newSelectedNodes: HTMLElement[] = Array.from(
    document.querySelectorAll('.row .seat.selected') as NodeListOf<HTMLElement>,
  );
  console.log(newSelectedNodes)

 // 전채 seat클래스들 중에서 selected된 div의 인덱스를 알아냄
  let seatsArr=Array.from(seats)
  let arr: number[] = newSelectedNodes.map((i) => {
    return seatsArr.indexOf(i);
  });
  console.log(arr)
profile
웰시코기발바닥

0개의 댓글