XHR 이란?

자바스크립트의 XMLHttpRequest 객체를 통해 구현 할 수 있다. AJAX 라고 부르기도 한다. 페이지 새로고침 없이 , 비동기적으로 서버에 요청을 보내고 응답을 받아오기 위해 사용한다.

 

구조

 

 

속성과 메서드, 이벤트

정적 속성
- UNSENT : XHR 객체의 readyState 속성 값으로 0과 같고, XHR 객체가 객체화된 후 아무런 동작을 하지 않은 초기 상태이다.
- OPENED : XHR 객체의 readyState 속성 값으로 1과 같고, open 메서드 호출 후의 상태이다.
- HEADERS_RECEIVED : XHR 객체의 readyState 속성 값으로 2과 같고, send 메서드 호출 후 서버와의 연결을 수립한 상태이다.
- LOADING : XHR 객체의 readyState 속성 값으로 3과 같고, 서버의 응답이 수신되기 시작한 상태이다.
- DONE : XHR 객체의 readyState 속성 값으로 4과 같고, XHR 통신이 성공 여부와 관계 없이 종료되었음을 의미한다.(통신 성공 여부는
status 속성 값이 200 이상 300 미만인지의 여부로 판단해야 한다.)


객체 속성
- readyState : XHR 객체의 대기 상태(숫자)이다.
- responseText : 서버가 응답으로 전송한 문자열 데이터이다.
- status : XHR 객체의 HTTP 상태 코드이다.
* 200 : OK . 정상상태 ( 200 이상 300 미만의 값을 정상 상태로 간주한다. )
* 400 : Bad Request . 서버가 요청하고 있는 데이터를 클라이언트가 누락하였거나 그 데이터의 형태가 잘못되었음을 의미한다.
* 404 : Not Found . 해당 경로에 대한 맵핑(엔드포인트)이 서버에 존재하지 않는다는 의미이다.
* 405 : Method Not Allowed . 경로는 존재하지만 해당 요청 방식(Method)으로 접근할 수 없다는 의미이다.
* 500 : Internal Server Error . 요청을 처리하는 도중 서버 내부에서 오류가 발생하였다는 의미이다.


객체 메서드
- abort( ) : send 메서드 호출 이후 요청에 대한 응답 대기를 취소한다.
- open(m, u) : 요청을 보낼 준비를 하기 위해 호출한다. 요청을 보낼 방식(Method)인 문자열을 m, 주소인 문자열을 u 에 전달한다.
- send(d) : 요청을 실질적으로 전송한다. 이 때 d 는 요청에 함께 보낼 데이터이며, 보낼 데이터가 없다면, 생략가능하다. 단 요청방식
  (open 메서드의 m 인자)이 GET 일 경우 데이터 인자( d ) 전달이 불가능하다.


객체 이벤트
- onabort : 응답 대기 상태에서 abort 메서드가 호출되었을 때 실행할 이벤트 함수
- onerror : 요청 도중 오류가 발생하였을 때 실행할 이벤트 함수
- onprogress : 서버로 부터 데이터를 수신 받을 때 마다 실행할 이벤트 함수
- onreadystatechange : XHR 객체의 readyState 속성 값이 변할 때 마다 실행할 이벤트 함수
- ontimeout : 응답 대기 시간이 지정한 제한 시간을 초과하엿을 때 실행할 이벤트 함수

 

 

 

실습

 

요청을 하기 위해 보낼 준비를 하는 메서드 open 부분의 저 주소는 현재 내 컴퓨터의 아이피 주소를 반환하는 주소이다.

xhr.readyState는 주로 0,1, 2, 3, 4를 리턴하는데, 이는 정적 속성 부분을 나타내는 숫자이다. 호출, 호출 수 수신 등등

xhr.status는 XHR 객체의 대기 상태인데, 200일 경우 요청 성공, 그 외에는 요청 실패이다.

xhr.responseText는 불러온 요청을 문자열로 반환된 상태이다. 

 

 

 

버튼을 누르고 네트워크에 가면, json 형식의 요청이 왔는데, 응답 부분을 누르면 오브젝트 형식의 값이 뜬다.

저 값을 문자열로 반환된 상태로 불러오는 것이 xhr.responseText이다. 이를 풀기 위해서는 JSON.parse( ) 메서드를 쓰면 된다.

 

 

FileReader 객체

FileReader 객체는 웹 어플리케이션이 비동기적으로 데이터를 읽기 위해 읽을 파일을 가리키는 File 혹은 Blob 객체를 이용해 파일의 내용을 읽고 사용자의 컴퓨터에 저장하는 것을 가능하게 해준다.

File 객체는 <input> 태그를 이용하여 유저가 선택한 파일들의 결과로 반환된 FileList 객체, 드래그 앤 드랍으로 반환된 DataTransfer 객체 혹은 HTMLCanvasElement의 mozGetAsFile() API로부터 얻는다.

 

 

 

예시

FileReader를 이용하여 이미지 파일을 선택했을 시 이미지 미리보기를 만들어 보았다.

파일Input에 onchange 이벤트를 걸어, 파일을 선택하였을 시 이벤트가 일어나도록 하였다. 먼저 선택한 파일을 가져와서

파일이 이미지 타입이 아닐 경우 그냥 종료시킨다. 이미지 파일을 불러왔을 시, 해당 파일을 데이터 형식으로 읽고 전부 읽으면 onload 이벤트가 발생하여 reader객체의 result 프로퍼티로 파일 이미지가 뜨게 한다.

 

 

 

이미지를 선택하였을 시, 이미지가 뜬다.

 

 

 

 

이미지파일이 아닌 txt 파일을 선택하였을 시, 아무런 이미지가 뜨지 않는다.

프로미스(Promise)란?

자바스크립트는 비동기 처리를 위해 콜백함수를 사용한다. 하지만 콜백을 너무 남용하면 콜백 지옥에 빠질 수 있다. 그리고 에러처리 역시 힘들고 여러개의 비동기처리를 한번에 하는데 한계가 있다. 이를 보완하기 위해 사용되는 객체가 프로미스이다.

 

 

프로미스의 이점

1) 비동기 처리 시점을 명확하게 표현

2) 연속된 비동기 처리 작업을 수정, 삭제, 추가하기 편하고 유연

3) 비동기 작업 상태를 쉽게 확인

4) 코드의 유지 보수성 증가

 

 

 

예시

 resolve가 실행되면 resolve에서 실행한게 value에 들어옴

reject가 실행되면 reject에서 실행한게 reason에 들어옴

catch는 reason만 처리됨

finally는 실패든 성공이든 무조건 동작

이들은 모두 순차실행인데, 병렬실행을 할 수 있다 (All 등)

 

 

3개의 프로미스를 순차적으로 만들었다. 3초 뒤에 1번이 실행되고, 그 다음 2초 뒤 2번에 실행되고, 그 다음 1초 뒤 3번이 실행된다.

 

 

 

ALL

all은 전달한 모든 프로미스를 병렬 동작 시키고, 전부 수행이 끝나면 종료된다. 전달된 프로미스들은 서로와 관계 없이 개별 동작을 수행한다.

전달된 프로미스 중 하나라도 reject 상태가 되면 즉시 종료된다. 먼저 'ERROR-1초'는 resolve이기 때문에 넘어가고 그 다음 'ERROR-2초'는 reject이므로 콘솔창에 실패가 뜨고 즉시 종료된다. 그러니 다음 'ERROR-3초'는 전달되지 않는다.

 

 

 

 

RACE

race는 전달한 프로미스들을 전부 병렬동작 시키고, 제일 빨리 성공(resolve)된 프로미스를 전달(반환)하고 끝난다.

제일 빠른게 1이니 1번을 전달하고 끝난다.

 

 

 

 

allSettled

전달받은 프로미스가 모두 성공 혹은 실패가 되면 처리결과를 배열로 반환

 

 

 

 

HTML로 만든 캐러셀 구조. i태그가 누르면 슬라이드 되는 버튼이고, carousel-wrapper는 한개의 이미지만 보일 수 있게 hidden을 처리할 예정. 그리고 캐러셀 클래스 내에 a태그 안에 이미지와 설명을 위한 span을 넣는다.

그리고 가장 밑에 circle은 슬라이드가 현재 어디를 가리키고 있는지 보여주는 동그라미

 

 

 

 

carousel-wrapper에 오버플로우 hidden 처리를 하면 사진 하나만이 화면에 나타나게 한다. 그리고 carousel 태그를 flex정렬 설정하여 사진들을 가로로 딱 붙히고, 캐러셀이 움직일 경우 0.2초 트랜지션을 설정하여 움직이게 한다. 사진의 크기는 넓이 700px 높이 400px로 통일한다.

 

 

 

 

동그라미 역시 flex로 설정하여 가로 정렬 한다. 그리고 circleActive라는 html에는 없는 class CSS를 만든다.

만약 내가 특정 슬라이드를 보여주고 있다면 class를 추가, 제거 하는 방식으로 동그라미 표시가 구현되게끔 할 것이다.

 

 

 

 

만든 모습

 

 

 

이제 캐러셀이 제대로 동작하도록 자바스크립트를 이용한다. 캐러셀 버튼들, 이미지, 표시할 동그라미 등등을 불러오고

이전 버튼을 클릭하였을 시, 만약 인덱스가 0이라면 이전 버튼을 눌러도 실행되지 않도록 했고, 인덱스를 -1씩 감소시킨다. 그리고 캐러셀의 스타일의 트랜스폼을 불러와서 이미지 넓이 X 인덱스 크기 만큼 이동시켜 캐러셀이 작동되도록 하였다.

캐러셀 이미지를 3개 만들었기에 다음 버튼을 클릭사였을 시, 만약 인덱스가 2이라면 다음 버튼을 눌러도 실행되지 않도록 하였고, 인덱스를 +1 씩 증가시킨다. 그리고 마찬가지로 캐러셀이 작동되도록 하였다.

 

그리고 인덱스를 표시할 동그라미,  이전 버튼을 누를 시 , 현재 인덱스의 동그라미 표시를 나타내는 클래스 classActive를 추가하고, 이전 인덱스의 classActive는 삭제한다. 다음 버튼을 누를 때도 똑같이 적용한다. 차이점은 이전 버튼을 누를 시, 뒤에 있는 인덱스의 동그라미 표시를 삭제하고, 다음 버튼을 누를 시, 앞에 있는 인덱스의 동그라미 표시를 삭제한다.

 

 

 

 

확인 결과 정상적으로 캐러셀이 동작하였다.

 

 

 

 

'JavaScript' 카테고리의 다른 글

[JavaScript] Image 미리보기  (0) 2023.07.12
[JavaScript] 프로미스 (Promise)  (0) 2023.07.11
[JavaScript] 간단한 자동차 게임 만들기  (0) 2023.07.08
[Javascript] localStorage  (0) 2023.07.05
[JavaScript] 요소 옮기기  (0) 2023.06.29

https://youtu.be/gD4fdiEsChU

 

자바 스크립트로 프로젝트를 하나 만들었는데, 옛날 테트리스 게임기에 수록되어 있었던 자동차게임을 만들었다.

 

이렇게 적 자동차를 좌우 방향으로 피하는 옛날 게임. 

원래 자바스크립트로 게임을 만드려면 canvas를 이용하느게 유용하고 쉬운 방법이지만, 아직 canvas를 배우지 않았고

내가 그동안 배운 것들을 종합해서 만들고 싶었기 때문에 canvas를 미사용하여 게임을 만들었다.

 

 

 

 

먼저 HTML과 CSS로 화면을 만들었다. 처음에 나는 적 자동차를 HTML에 만들지 않고 자바스크립트로 생성후 Y축으로 이동하여 완전히 이동했으면 그 요소를 지우고 요소를 다시 생성하는 방식으로 게임을 만드려고 했다. 하지만 그걸 구현하기에는 매우 어렵고 헷깔리기도 하고, 또.. 화면에 나타나는 적 자동차가 2개 밖에 안 되고, 똑같은 장면만을 반복하기에 굳이 그럴 필요가 없다고 판단했다. 그냥 적 자동차를 HTML로 미리 만들어 놓고, y축으로 이동 후, 완전히 이동했을 시, 그냥 y축을 초기화해서 다시 시작 지점으로 갖다 놓고, 그걸 무한반복하면 된다.

 

그리고 충돌 이미지도 HTML에 생성했는데, 이 이미지는 display : none으로 평소에 보이지 않을 뿐,  내 자동차가 좌우로 움직일 때 같이 움직인다. 충돌 시 [active] 설정으로 충돌 이미지가 보이도록 설계하였다.

 

 

 

 

자바스크립트 부분이다. 여러 변수들을 만들었다. 게임 최초 시작시, 준비시간을 설정해놓기 위해 만든 준비시간 변수, 남은 생명 변수, 스코어 변수, 게임오버 변수 등등. 게임에 필요한 여러 변수들을 미리 만들어 놓았다

 

 

 

맨 처음 적 자동차 2개가 좌 혹은 우측에서 랜덤으로 나오게하기 위해 랜덤숫자를 이용했다. 1부터 10까지 랜덤 숫자가 설정되는데, 1에서 5까지는 적 자동차가 X축으로 185px(우측), 6에서 10까지는 X축으로 40px(좌측)에서 나타나도록 설정하였다.

 

 

게임시작 버튼, 중지버튼을 누르면 각각 게임시작, 게임중지가 되도록 설정하였다. 게임 시작, 중지 버튼이 아니더라도 방향키 UP을 누르면 게임시작, down을 누르면 게임 중지가 되도록 설정하였다. 그리고 미리 만들어둔 ready 변수가 0일 경우(게임을 최초로 시작할 경우) setTimeout으로 게임시작 전 2초간 준비시간을 준다. 그리고 ready 변수는 1로 만든다. 그러면 게임 중지를 누르고 다시 게임시작을 누를 경우 더이상 2초간 준비시간을 주지 않는다.

 

 

 

내 자동차 좌우 움직이기 함수, 방향키 오른쪽을 누를 시, x축은 185px(우측), 방향키 왼쪽을 누를 시 x축이 40px(좌측)으로 움직이게 만들었다.

 

 

 

이제 게임 시작 함수, 게임시작 버튼 혹은 방향키 up을 누를시 실행되는 함수이다. 레벨에 따라 스피드와 화면에 표시될 레벨을 다르게 설정하였다. gameSpeed 변수는 게임을 움직일 setInterval 함수에 집어넣어 게임의 속도를 변화시키는 중요한 변수이다. 그리고 addEventListener로 키보드 방향키로 내 자동차 좌우 움직이기가 가능하도록 했다.

 

 

이 역시 start 함수에 들어있다. gameStart 변수에 setInterval로 게임 동작 함수를 넣고, gameSpeed 함수를 집어넣어 게임이 실행되도록 하였다. 그리고 gameStart 변수가 0보다 클 경우 게임시작 버튼을 여러번 클릭해도 중복해서 실행되지 않도록 하였다.

 

 

 

일시중지버튼 혹은 키보드 방향키 아래쪽을 누를 경우 게임이 일시 중지 되도록 일시중지 함수를 만들었다. clearInterval로 동작하고 있는 게임을 멈추고, gameStart 변수도 -1로 설정하여 다시 게임시작을 눌렀을 경우 게임이 시작되도록 하였다. 그리고 일시중지일 경우 좌우 방향키가 먹히지 않도록 하기 위해 removeEventListener를 걸었다.

 

리셋함수는 자동차가 충돌했을 경우 모든 요소들을 원래대로 돌려놓기위해 만들었다. 내 자동차 위치도 원래위치(좌측)로 이동하게 했고, 충돌 이미지도 똑같히 설정했다. 적 자동차도 좌측 혹은 우측에서 랜덤으로 위치시켰고, 게임 시작했을 경우 누를 수 없었던 레벨 선택 input도 다시 활성화 그리고 stop함수를 실행시켜 게임을 멈춘다.

 

 

 

대망의 게임 실행 함수... 위 코드는 게임 동작 함수 function move() 안의 코드들이다.  적 자동차가 2개인데,  하나는 처음 동작할때 18초의 딜레이를 두게 했다. 왜냐하면 2개 모두 동시에 움직일 경우 어쩔 수 없이 게임오버가 될 수 밖에 없기 때문이다. 2개의 적 자동차 각각 y축으로 20px씩 이동하게 하였고, y축이 550보다 크다면(다 지나갔다면) 다시 y축을 -120px(처음 시작위치) 로 초기화한다. 그리고 다 지나갔으면 점수도 10씩 올린다. 그리고 다시 랜덤 숫자를 이용하여 좌측 혹은 우측에서 적 자동차가 나타나게끔 하였다.

 

 

 

충돌 일 경우 게임오버 변수를 true로 만든다. 내 자동차는 y축이 변하지 않기 때문에 적 자동차가 내 자동차의 y축 근처에 다다랐을 경우, 내 자동차와 적 자동차의 x값을 비교하여 같다면 충돌을 인식하도록 하였다. 그리고 보이지 않던 충돌 이미지도 toggleAttribute로 나타나게 하였다.

 

 

충돌했을 경우 gameOver 변수가 true가 되는데, 이때 reset 함수를 실행시켜 게임을 리셋하고, gameOver = true로 인해 move() 함수는 더이상 실행이 되지 않기 때문에 다시 gameOver 변수를 false로 변경한다. 그리고 목숨 하나를 잃게하고 게임 화면에 나타내고 알림으로 알려준다. 그리고 충돌 이미지를 다시 toggleAttribute로 없앤다.

 

 

 

목숨이 0이 됐다면 최종적으로 게임오버가 됐기 때문에, 목숨을 다시 초기화하고 스코어 역시 초기화한다. 스피드도 초기화, 레벨도 초기화... 그리고 게임 스코어를 저장하기 위해 localStorage를 이용하였다.

 

 

이 코드도 move 함수에 들어있는 코드다. 점수 200점씩 받으면 레벨이 한단게 올라가도록 설정하였고, 게임스피드가 20이이 됐을 경우(레벨 5가 되었을 경우) 가장 큰 레벨이기 때문에 더이상 레벨업을 할 수 없도록 설정했다. 그리고 스코어가 200이 됐을 경우 이 역시 여기에 걸려서 레벨 업을 할 시 다시 게임이 실행되지 않기 때문에 storageScore라는 스코어 저장 변수에 얻었던 스코어 200점을 저장해놓고, 스코어 변수는 다시 0이 되게 하였다. 그리고 현재 실시간 점수를 화면에 나타나게 스코어보드의 textContent에 스코어변수와 저장스코어변수를 합친 값을 넣었다.

 

 

 

완성된 게임! 옛날에 재미있게 플레이했던 게임을 직접 만들어서 플레이하니 감회가 새롭다.

localStorage란?

로컬 스토리지를 사용하여 key-value 값을 스토리지에  저장할 수 있다. 저장한 데이터는 세션간에 공유된다.

세션이 바뀌어도 저장한 데이터는 유지 된다는 이야기다.

 

 

 

예시

먼저 HTML을 저렇게 설정 후, key값과 value 값을 입력한 뒤에 그것을 로컬 스토리지에 저장하기로 하였다.

setItem으로 키, 값을 추가하고, getItem으로 key의 value값을 웹 페이지에 보여지도록 하였다.

 

 

 

이렇게 키 : 홍길동, 값 : 28로 설정하면 로컬 스토리지에 저장이 된 걸 확인할 수 있다.

 

 

 

getItem을 설정했기 때문에 웹 페이지를 보면 저장했던 키의 값이 보여진다.

 

 

 

먼저 HTML과 CSS를 이렇게 설정한다.

 

 

 

마우스를 클릭했을 시, 이동 이벤트를 걸어준다. 이동한 거리는 마우스의 현재 위치에서 처음 클릭 위치를 빼면 된다.

그리고 움직이는 요소의 CSS transform을 변경하여 요소의 위치를 바꿔준다.

 

마우스를 놨을 때 이미 걸어줬던 move 이벤트를 취소하여 움직이지 않도록 한다.

마우스는 놓고 다시 마우스를 클릭했을 때, 요소가 그 자리에 있게끔 하기 위해서는

현재 마우스의 위치값 변수를 마우스의 현재위치에서 이동한 거리를 뺀 것으로 지정하면

요소를 다시 클릭해도 그 자리에 있게 된다..

 

 

 

먼저 div 상자 3개를 만든 후, CSS를 이용하여 맨 아래 이미지처럼 만들었다.

 

 

 

모든 div태그를 불러온 뒤, divs에 저장한다. getElementByTagName으로 불러왔기에, divs는 모든 div들이 저장되어있는 배열이다. 배열 divs를 foreach로 하나씩 불러오게하여, draggable = true;를 이용하여 모든 div 태그가 드래그가 가능하도록 한다.

 

그리고 dragstart를 이용하여 처음 스크롤을 누를 시, div의 텍스트와 배경색을 저장하도록 만든다. dataTransfer.setData를 이용하면 보다 쉽게 div의 데이터 정보들을 저장할 수 있다.

 

dragover 이벤트를 이용해서, e.preventDefault();로 기본동작을 취소해야 한다.  취소하지 않으면 아래의 drop 이벤트가 취소되기 때문이다.

 

drop 이벤트는 드랍할 대상 요소에 적용을 한다. 드랍할 대상 요소 역시 같은 div들 중 하나이므로, div에 적용을 한다. 대상 타겟의 textContent에 getData로 저장되었던 텍스트를 집어넣고, 해당 div의 backgroundColor에 저장되었던 색깔 데이터를 집어넣는다.

 

 

 

파란색 text3 상자를 빨간색 text1 상자에 드래그한 모습이다. 빨간색 text1 상자가  text3 상자처럼 변했다.

 

 

 

 

드래그 이벤트 종류

드래그하는 대상에 적용

dragstart : 드래그를 시작할 때 발생

drag : 드래그를 하는 동안 발생

dragend : 드래그가 끝났을 때 발생

 

드랍할 대상 요소에 적용

dragenter: 마우스 포인터가 드롭 요소의 경계선 안쪽으로 들어갈 때 발생

dragover: 마우스 포인터가 드롭 요소의 경계선 안쪽에 있을 때 발생

dragleave: 마우스 포인터가 드롭 요소의 경계선 바깥으로 나왔을 때 발생

drop: 요소에 드롭할 때 발생

 

 

 

html을 이용하여 타이머를 만든다.

 

 

 

 

먼저 표시할 타이머(h1)와 버튼들을 불러온다.

 

 

 

 

타이머 기능을 할 함수를 만든다. second에 1을 계속 증가시키고, 만약 second가 60이 되었다면, minute에 1을 증가시킨다. 그리고 second는 다시 0으로 초기화 한다. 그리고 minute가 60이 되었을 때 역시 마찬가지로 hour에 1을 증가시키고 minute는 0으로 초기화 한다.

 

10의 자리 표시, 만약 second가 1의 자리 수라면 secondTen은 0으로 표시하고, 10 이상 수라면 공백으로 표시한다. 분과 시간 역시 동일하게 적용한다. 그 후 textContent를 이용하여 h1에 함수에서 설정한 값대로 타이머를 적용시킨다.

 

 

 

 

먼저 setInterval을 넣을 변수 id를 만들고, 각 버튼을 클릭할 시 작동할 함수의 이름들을 적는다.  이제 버튼에 적용한 함수들을 만들어 볼 차례...

 

 

 

 

먼저 시작버튼을 눌렀을 시, 미리 만들어놓은 id 변수에 setInterval을 넣고, setInterval 요소에 이미 만든 타이머 함수를 넣고, 1000ms (1초) 마다 실행시킨다. 그럼 타이머가 실행된다.

 

일시중지 버튼을 눌렀으면, clearInterval을 실행시켜 비동기실행이 잠시 중단되도록 한다.

 

리셋버튼을 누를 시, 모든 초, 분, 시의 값들을 0으로 초기화시키고, 각각의 10의 자리 수의 값들도 초기화시킨다. 그리고 h1.textContent로 다시 타이머를 00:00:00으로 표시하게 한 후,  clearInterval을 실행시켜 타이머를 정지시킨다.

 

 

 

 

확인 결과 정상적으로 타이머가 작동한다.

 

 

 

 

먼저 부모요소 div에 자식요소인 button을 만든다. 그리고 부모요소 div를 클릭할시 div의 배경색을 검은색으로 변하게 한다. 그 결과 부모요소인 div를 클릭하면 배경색이 검은색으로 변한다. 그런데?? 자식요소인 button을 눌렀을때도 똑같이 변한다? 그 이유는 자식요소의 이벤트가 발생했을때, 그것이 부모요소에 전파되기 때문에, 자식요소를 클릭했음에도 부모요소에 설정한 대로 변하게 된다.

 

 

 

 

그럼 이번에는 자식요소를 클릭했을때, 부모요소에 이벤트가 발생하는걸 취소해보자. 자식요소 button을 클릭했을 시, stopPropagation()을 이용하여 부모요소에 이벤트 전파가 취소되게끔 하였다. 그 결과 자식요소 button을 클릭하면 부모요소의 배경색을 변하지 않고, 부모요소를 클릭했을 때만 배경색이 변화한다.

 

 

 

 

자식 요소의 또 다른 이벤트까지 취소하고 싶다면, stopImmediatePropagation()을 이용한다. 그럼 자식 요소인 button을 클릭했을 시, button 본인에게 걸려진 다른 이벤트 역시 실행되지 않는다.

 

 

 

 

+ Recent posts