Web Component Event Dispatching 하기

앞서 만든 Web Component로 부터 이벤트에 따른 변화를 알아야 한다면 어떻게 해야 할까?

가련 버튼을 클릭한 이벤트의 횟수를 외부에서 알아야 한다면?

두가지 방법이 있다.

  • get 을 이용해서 public value를 알아 내는 방법
    get timesClicked(){
        return this.timesClicked;
    }
  • 또 하나는 Event를 통해서 업데이트 된 Data를 알아내는 방법이다.

 

여기서 두번째 방법에 대해서 알아보고자 한다.

Event Button component 설계

<event-button onchange="eventChecker(event.detail)"></event-button>

html tag에서 onchange라고 하는 event를 등록하면 event를 수신받을 수 있도록 만들어 준다.

 

Event Button component 개발

export default class EventButton extends HTMLElement {
    constructor(){
        super();
        this.timesClicked = 0;

        this.shadowObj = this.attachShadow({mode:'open'});

        this.render();
    }

    getTimeClicked(){
        return `Times clicked : ${this.timesClicked}`
    }

    render(){
        // this.innerHTML = this.getTemplate();
        this.shadowObj.innerHTML = this.getTemplate();
    }

    getTemplate(){
        return `
            <button> Click Me </button>
            <span> ${this.getTimeClicked()} </span>
            ${this.getStyle()}
        `;
    }

    get timesClicked {
        return this.timesClicked;
    }

    getStyle(){
        return `
            <style>
            :host {
                display : block;
            }

            button {
                height:50px;
                width:200px;
                border-radius:5px
                display:inline-block;
                border: 1px solid #cac6c6
            }
            </style>
        `;
    }

    handleClick(){
        this.timesClicked++;
        this.shadowObj.querySelector('span').innerText = this.getTimeClicked();

    }

    connectedCallback(){
        this.shadowObj.querySelector('button').addEventListener('click', this.handleClick.bind(this));

    }

    disconnectedCallback(){
        console.log('Button Disconnected Callback');
        this.shadowObj.querySelector('button').removeEventListener('click',this.handleClick);

    }

    static get observedAttributes(){
        console.log('observedAttributes');
        return ['btitle'];
    }

    attributeChangedCallback(attName, oldValue, newValue){
        console.log(attName, oldValue, newValue);
        this.shadowObj.querySelector('button').innerText = newValue;
    }

    adoptedCallback(){
        console.log('move to somewhere');
    }

};

customElements.define('event-button', EventButton);

 

상기 코드는 

click Me 버튼을 click하면 times clicked의 cout가 내부적으로 업데이트 되는 컴포넌트 이다.

이것을 외부로도 event를 통해서 연결해 주는 것이 목표이다.

 

그러기 위해서는 click me라고 하는 버튼의 이벤트가 내부적으로 어디에 연결 되어있는지 확인해 봐야 한다.

    connectedCallback(){
        this.shadowObj.querySelector('button').addEventListener('click', this.handleClick.bind(this));

    }

DOM에 해당 컴포넌트가 add 될때 button에 this.handleclick과 연결해 놓은 것을 알 수 있다.

그럼 이 handle click 이 들어올때 외부로 이벤트를 연결할 수 있는 통로를 만들어 주자.

    handleClick(){
        this.timesClicked++;
        this.shadowObj.querySelector('span').innerText = this.getTimeClicked();

        this.dispatchEvent(new CustomEvent('change', {
            detail : {num : this.timesClicked},
            bubbles: true
        }));
    }

this.dispatchEvent에 customEvent를 설정함으로써 처리하는 쪽에서 event.detail로 필요한 값을 얻을 수 있게된다.

위에서 bubbles는 기본적으로 false인데, bubbling이 필요할 수 있음으로 true로 변경해 놓았다.

event에 들어갈 수 있는 init 값은 아래에서 참조 가능하다.

https://developer.mozilla.org/en-US/docs/Web/API/Event/Event

 

html에서 event 연결

이제 해당 tag의 event를 html tag를 통해서 연결할 수 있게 되었다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <event-button onchange="eventChecker(event.detail)"></event-button>

    <script type="module" src="EventButton.js"></script>

    <script>
        function eventChecker(e) {
            console.log('button event cliecked = ' + JSON.stringify(e));
        }
    </script>
</body>
</html>

onchange="eventChecker(event.detail)"

를 통해서 detail 정보를 전달할 수 있는데, 여기서 주의 해야할 것은 반듯이 event.detail이다.

그래야 내가 보내고 싶은 값은 전달 할 수 있다.

물론 event 자체로 내려보내도 되긴 하지만 사용하기가 다소 어려운 부분이 있다.

이벤트가 연결되어서 컴포넌트 내부 및 외부에도 정보를 넘기는 것을 확인 가능하다.

2021.08.16 - [Web] - 기존 web site를 components 로 다시 만들기 (No State management)

 

기존 web site를 components 로 다시 만들기 (No State management)

Web Components가 무었인지에 대해서는 2021.08.14 - [Web] - Web component (Custom Elements, Shadow DOM, Template) 2021.08.14 - [Web] - Web Components Callback Methods & lifecycle 2021.08.14 - [Web] -..

enumclass.tistory.com

 

728x90
반응형