Recent Posts
Recent Comments
Link
11-21 14:38
Today
Total
관리 메뉴

삶 가운데 남긴 기록 AACII.TISTORY.COM

javascript event 본문

DEV&OPS/Javascript

javascript event

ALEPH.GEM 2022. 3. 11. 22:28

이벤트 리스너(listener) 등록 방법

HTML과 DOM에 이벤트 리스너는 하나만 등록할 수 있습니다. 

증복해서 등록할 경우 이전에 등록한 핸들러는 무시됩니다.

HTML attribute
<input type="button" onclick="changeColor();">
DOM
var btn = document.getElementById("button");
btn.onclick = changeColor();
element.addEventListener(type, listener, useCapture)

type : 이벤트 유형

listener : 이벤트 처리를 담당할 콜백 함수 참조

useCapture : 캡처링 단계(true), 버블링 단계(false) , 생략 가능 

var btn = document.getElementById("button");
btn.addEventListener("click", changeColor, false);

addEventListener는 이벤트 핸들러를 중복해서 여러개 등록할 수 있습니다.

버블링 단계와 캡처링 단계 모두 활용하고 이벤트 전파를 제어할 수 있습니다.

 

 

이벤트 리스너 삭제

element.removeEventListener(type, listener, useCapture);

등록한 이벤트 리스너를 삭제 합니다. 단, 익명함수로 등록한 리스너는 삭제 할 수 없습니다.

이벤트 리스너를 삭제 하려면 그 함수의 참조를 저장하고 있어야 하지만 이 메서드를 이벤트 리스너 안에서 호출하여 스스로 삭제하는 방법이 있습니다. 이때는 listener 인수에 arguments.callee 를 전달 합니다.

window.onload = function(){
    var element = document.getElementById("button");
    element.addEventListener("click", function(){
        console.log("hello");
        element.removeEventListener("click", arguments.callee, false);
    }, false);
};

 

 

이벤트 객체(예제에서는 e)의 공통 프로퍼티: 이벤트 함수의 인수값으로 전달하는 객체

e.type  //이벤트의 이름(string)

e.target  //이벤트의 대상이 되는 element(아래 예제에서는 img태그) 

e.currentTarget   //현재 호출되는 이벤트 리스너를 등록한 element 

e.eventPhase   //이벤트 생명주기 단계 number로 return

e.bubbles    //이벤트가 문서를 통해 버블링 되면 true, 아니면 false를 return

e.cancelable  //이벤트에 취소할 수 있는 기본 동작이 있으면 true, 없으면 false를 return

e.stopPropagation()   //현재 element에 대한 이벤트 리스너를 실행 한 후 이벤트 흐름(bubbling)을 중단 void

e.stopImmediatePropagation()   //즉각 중단, 호출되지 않은 이벤트 리스너는 무시 됨 void

e.preventDefault()      //브라우저가 이벤트와 관련한 동작을 수행하지 못하게 함 void

e.defaultPrevented   //preventDefault()가 호출된 경우 true 아니라면 false를 return

 

예제
<script>
/* html태그에 img 태그들이 있다고 가정 */
/* 이미지 태그 img들의 배열로 리턴하는 메서드 예제 */
var elements = document.getElementsByTagName("img");   

for(var i = 0; i < elements.length; i++){
	consol.log(elements[i].tagName +" " + elements[i].src);
	/* DOM 객체의 attribute(속성) 수정 */
	elements[i].src = "exampleimage.jpg";
	/* DOM 객체의 스타일(투명도를 0.5로) 수정 */
	elements[i].style.opacity = 0.5;
	/* 이벤트 처리 */
	elements[i].onmouseover = handleMouseOver;
	elements[i].onmouseout = handleMouseOut;
}

/* handleMouseOver 이벤트 처리 함수 */
function handleMouseOver(e) {
	e.target.style.opacity = 1;
}

/*  handleMouseOut 이벤트 처리 함수 */
function handleMouseOut(e){
	e.target.style.opacity = 0.5;
}

</script>

 

 

마우스 이벤트 객체의 공통 프로퍼티

  • screenX, screenY : 이벤트가 발생한 위치의 화면 좌표
  • clientX, clientY : 이벤트가 발생한 위치의 윈도우 창 좌표
  • pageX, pageY : 이벤트가 발생한 위치의 문서(document) 좌표
  • offsetX, offsetY : 이벤트가 발생한 요소(element)의 상대 좌표
  • altrKey : alt키가 눌렸는지 여부(boolean)
  • ctrlKey : ctrl키가 눌렸는지 여부(boolean)
  • shiftKey : shift키가 눌렸는지 여부(boolean)
  • detail : 이벤트의 상세 정보(클릭한 횟수)
  • button : 0:왼쪽버튼, 1:휠버튼, 2:오른쪽 버튼
  • relatedTarget : mouseover에서는 마우스가 떠난 element노드, mouseout에서는 마우스가 들어온 element노드

 

 

키보드 이벤트 객체의 공통 프로퍼티

  • altKey : alt키가 눌렸는지 여부
  • ctrlKey : ctrl키가 눌렸는지 여부
  • shiftKey : shfit키가 눌렸는지 여부
  • metaKey : meta키(윈도우키, Command키)가 눌렸는지 여부
  • key : 눌린 키의 DOM String
  • keyCode : 눌린키의 식별 코드
  • code : 눌린 키의 물리적 위치를 뜻하는 문자열
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title> </title>
</head>
<body>
    <p id="display"></p>
    <script>
        window.onload = function(){
            document.addEventListener("keydown", showKey, false);
            var display = document.getElementById("display");
            function showKey(e){
                var prop = ["altKey","ctrlKey", "shiftKey", "metaKey","key","code","keyCode"];
                var s = "";
                for (var i in prop){
                    s += "<br>" + prop[i] + ": " + e[prop[i]];
                }
                s += " -> " + String.fromCharCode(e.keyCode);
                display.innerHTML = s;
            }
        }
    </script>
</body>
</html>

 

 

이벤트의 단계

캡처링 단계

이벤트가 Window 객체에서 출발해서 DOM트리를 타고 이벤트 타겟까지 전파됩니다. 

이 단계에 등록된 이벤트 리스너는 이벤트가 발생한 요소의 이벤트 리스너보다 먼저 실행됩니다.

그래서 이벤트가 발생한 타겟이 이벤트를 수신하기 전에 이벤트를 먼저 가로채기(캡처) 할 수 있는 단계이기 때문에 캡처링 단계라는 이름이 붙었습니다.

타겟 단계

이벤트가 이벤트 타겟까지 전파되는 단계입니다.

이벤트 타겟에 등록된 이벤트 리스너는 이 시점에서 실행됩니다.

버블링 단계

이벤트가 이벤트 타겟에서 출발해서 DOM트리를 타고 Window 객체까지 전파됩니다.

이 단계에서 반응하도록 등록된 이벤트 리스너는 타겟 요소에 등록된 리스너를 처리한 다음에 실행됩니다.

단, focus와 blur 이벤트는 그 요소에만 필요한 이벤트라 버블링이 발생하지 않습니다.

이벤트 리스너는 실행단계를 선택할 수 있습니다. useCapture가 true이면 캡처링과 타겟 단계에서 실행되며, useCapture가 false면 타겟 단계와 버블링 단계에만 실행됩니다.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title> </title>
</head>
<body>
    <div id="outer">
        outer
        <div id="inner1">inner1</div>
        <div id="inner2">inner2</div>
    </div>
    <script>
        window.onload = function(){
            var outer = document.getElementById("outer");
            var inner2 = document.getElementById("inner2");
            outer.addEventListener("click", function(e){
                console.log("outer bubbling");
            }, false);  /* useCapture값이 false여서 버블링이 진행됩니다. */
            outer.addEventListener("click", function(e){
                console.log("outer capturing");
            }, true);   /* useCapture값이 true여서 캡처링이 진행됩니다. */
            inner2.addEventListener("click", function(e){
                console.log("inner2 bubbling");
            }, false);
        }
    </script>
</body>
</html>

inner2를 클릭하면 아래와 같이 콘솔 로그에 나타납니다.

outer capturing 
inner2 bubbling 
outer bubbling

캡처링이 먼저 실행된 뒤에 그다음 타겟이 실행되고 그 다음 버블링이 실행되는 것을 알 수 있습니다.

 

 

이벤트의 전파

event.stopPropagation() 

이벤트가 다음 요소로 전파되는 것을 취소합니다.

그 이벤트에 등록한 다른 이벤트 리스너는 실행됩니다.

event.ImmediatePropagation()

이벤트가 전파되는 것을 일시적으로 멈춥니다.

게다가 이 메서드는 다른 이벤트 리스너들도 일시 정지됩니다.

event.preventDefault()

브라우저에서 구현된 기본 동작(이벤트)를 취소합니다.

예를 들어 a 태그를 클릭하면 페이지가 이동되는데 이러한 이벤트 동작을 취소시킬 수 있습니다.

단, 이벤트 객체의 cancelable 프로퍼티가 false인 경우 취소할 수 없습니다. 

 

 

이벤트 리스너의 this

이벤트 리스너의 this는 이벤트가 발생한 element 객체를 참조하고 있습니다.

이벤트 리스너의 this를 특정 객체를 참조하도록 하는 방법에는 아래와 같은 방법들이 있습니다.

bind 메서드
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title> </title>
</head>
<body>
    <button id="button">버튼</button>
    <script>
        window.onload = function(){
            function Person(name){
                this.name = name;
            };
            Person.prototype.sayHello = function(){
                console.log("Hello! " + this.name);
            }
            var person = new Person("Jack");
            var button = document.getElementById("button");
            button.addEventListener("click", person.sayHello.bind(person), false);
        };
    </script>
</body>
</html>

그러면 this가 person을 가리키므로 콘솔에서는 Hello! Jack 이 표시됩니다.

익명 함수 안에서 실행하는 방법
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title> </title>
</head>
<body>
    <button id="button">버튼</button>
    <script>
        window.onload = function(){
            function Person(name){
                this.name = name;
            };
            Person.prototype.sayHello = function(){
                console.log("Hello! " + this.name);
            }
            var person = new Person("Jack");
            var button = document.getElementById("button");
            button.addEventListener("click", function(e){
                person.sayHello();
            }, false);
        };
    </script>
</body>
</html>
화살표 함수를 사용하는 방법
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title> </title>
</head>
<body>
    <button id="button">버튼</button>
    <script>
        window.onload = function(){
            function Person(name){
                this.name = name;
                this.sayHello = () => {
                    console.log("Hello! " + this.name);
                };
            }
            var person = new Person("Jack");
            var button = document.getElementById("button");
            button.addEventListener("click", person.sayHello , false);
        };
    </script>
</body>
</html>
addEventListener 의 두 번째 인수로 객체를 넘기는 방법
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title> </title>
</head>
<body>
    <button id="button">버튼</button>
    <script>
        window.onload = function(){
            function Person(name){
                this.name = name;
            }
            Person.prototype.handleEvent = function(){
                console.log("Hello! " + this.name);
            };
            var person = new Person("Jack");
            var button = document.getElementById("button");
            button.addEventListener("click", person , false);
        };
    </script>
</body>
</html>

 

이벤트 리스너에 추가 정보 전달 방법

이벤트 리스너는 이벤트 객체를 인수로 받습니다. 

이벤트 객체 외에 추가 정보를 이벤트 리스너에게 전달하려면 어떻게 해야 할까요?

익명 함수 안에서 함수 호출
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title> </title>
</head>
<body>
    <div id = "box">click</div>
    <script>
        window.onload = function(){
            var box = document.getElementById("box");
            box.addEventListener("click", function(e){
                changeBgColor(e,"red");
            }, false);
            function changeBgColor(e, color){
                e.currentTarget.style.backgroundColor = color;
            }
        };
    </script>
</body>
</html>
함수를 리턴하는 함수를 이벤트 리스너로 등록
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title> </title>
</head>
<body>
    <div id = "box">click</div>
    <script>
        window.onload = function(){
            var box = document.getElementById("box");
            box.addEventListener("click", changeBgColor("red"), false);
            function changeBgColor(color){
                return function(e){
                    e.currentTarget.style.backgroundColor = color;
                };
            }
        };
    </script>
</body>
</html>

 

커스텀 이벤트

var event = document.createEvent(type);

이벤트 객체를 생성합니다.

type은 이벤트 타입을 뜻합니다.

type 설명 초기화 메서드
UIEvents 사용자 인터페이스 이벤트 event.initUIEvent
MouseEvents 마우스 이벤트 event.initMouseEvent
TextEvent 텍스트 이벤트 event.initTextEvent
KeyboardEvent 키보드 이벤트 event.initKeyEvent
MutationEvents 변이 이벤트 event.initMutationEvent
HTMLEvents HTML 이벤트 event.initEvent
CustomEvent 사용자 지정 이벤트 event.initCustomEvent
event.initEvent(type, bubbles, cancelable);

type: 이벤트 유형(예: "click", "mouseup" 등)

bubbles : 버블링 여부 (boolean)

cancelable : 취소할 수 있는 이벤트인지 여부 (boolean)

var event = document.createEvent("HTMLEvents");
event.initEvent("click", true, false);
target.dispatchEvent(event);

타겟 요소를 상대로 이벤트를 보냅니다.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title> </title>
</head>
<body>
    <button id = "button">click</button>
    <script>
        window.onload = function(){
            var event = document.createEvent("HTMLEvents");
            event.initEvent("click", true, false);
            var button = document.getElementById("button");
            button.addEventListener("click", function(event){
                alert(`event.cancelable: ${event.cancelable}`);
            });
            button.dispatchEvent(event);
        };
    </script>
</body>
</html>

해당 이벤트 리스너가 동기적으로 실행됩니다.

표준 이벤트와 차이점

커스텀 이벤트는 이벤트 객체의 isTrusted 프로퍼티가 false 이면 커스텀 이벤트이고, true이면 표준 이벤트 입니다.

커스텀 이벤트의 용도

커스텀 이벤트는 이벤트 리스너가 동기적으로 실행됩니다.

객체와 객체가 통신하는 주요 수단은 인수로 콜백함수를 넘기는 방법이 있으며, 또 다른 하나는 커스텀 이벤트를 보내는 것입니다.

즉, 한쪽 객체에서는 이벤트를 발생시키고 다른 객체에서는 이벤트를 처리하는 리스너를 등록해서 처리하는 것입니다.

 

 

 

 

 

 

 

728x90

'DEV&OPS > Javascript' 카테고리의 다른 글

Ajax  (0) 2022.03.12
javascript 비동기 처리 Promise  (0) 2022.03.12
javascript DOM tree  (0) 2022.03.06
javascript 브라우저의 객체  (0) 2022.03.04
javascript 정규 표현식  (0) 2022.03.03