2017-11-11 1 views
1

TL; DR; 맞춤 이벤트에 대해 JS (JS가 아닌)로 이벤트 리스너를 정의 할 수 있습니까? 이 codepen 근거로웹 구성 요소/사용자 지정 이벤트 (JS) 용 HTML 기반 이벤트 수신기

, 나는 다음을 수행하려고 해요 : myFunction 내가 브라우저 콘솔에서 볼 수있는 몇 가지 console.log 물건을 수행

<my-checkreport 
    onclick="myFunction()" 
    oncheck="myFunction1)" 
    check="myFunction()" 
></my-checkreport> 

. 사용자 정의 이벤트에 대한 기본 onlick 물론 작품,하지만 어느 oncheckcheck 작품은 아래에 정의 된 (위에서 찍은 소스는 codepen를 연결) :

customElements.define('my-checkbox', class extends HTMLElement { 
    constructor() { 
    super(); 
    const shadowRoot = this.attachShadow({mode: 'open'}); 
    this.checkEvent = new CustomEvent("check", { 
     bubbles: true, 
     cancelable: false, 
    }); 
    shadowRoot.innerHTML = ` 
     <label> 
     <input type="checkbox" id="my-checkbox"></input> 
     Dummy Enabled 
     </label>`; 
    shadowRoot.querySelector('#my-checkbox').addEventListener('click', (e) => { 
     console.log('checked', e.target.checked); 
     this.dispatchEvent(this.checkEvent); 
    }); 
    } 
}); 

는 HTML에서 사용자 정의 이벤트에 대한 이벤트 리스너를 부착 할 수 있습니까?

+0

아마도이 대답은 도움이 될 수 있습니다. https://stackoverflow.com/a/41218056/4600982 또는 더 많은 가능성이 있습니다. https://stackoverflow.com/a/42321978/4600982 – Supersharp

답변

1

JS 코드가 없습니까? 아니요.하지만 요소의 속성을 가져 와서 평가하기 위해 요소의 생성자에서 속성을 정의 할 수 있습니다. 예를 들어,

constructor() { 
    // Other code. 
    const onCheckFunc = this.getAttribute('oncheck') 
    this.addEventListener('check',() => eval(onCheckFunc)) 
    // Rest of your code. 
} 

편집 : @Intervalia에서 언급 한 바와 같이, 당신은 constructor에있는 요소의 속성을 검사하지 않아야합니다. connectedCallback에서이 작업을 수행 할 수 있습니다. 하지만 기억 :

일반적으로
  • 이 작업이 가능 특히 가져 오는 자원이나 렌더링을 포함하는 작업만큼 connectedCallback로 연기되어야한다. 그러나 connectedCallback은 두 번 이상 호출 될 수 있으므로 실제로 한 번만 초기화하면 모든 작업이 두 번 실행되지 않도록 가드가 필요합니다.
  • 일반적으로 constructor은 초기 상태 및 기본값을 설정하고 이벤트 리스너와 섀도우 루트를 설정하는 데 사용해야합니다.
+0

웹에 대한 기억 생성자의 속성을 읽는 구성 요소 규칙입니다. https://w3c.github.io/webcomponents/spec/custom/#custom-element-conformance * 요소의 속성 및 하위 항목을 검사해서는 안됩니다 ... * – Intervalia

2

이것은 가장 가까운 이벤트 처리기의 DOM 선언을 에뮬레이트 할 수있는 것입니다. 이 코드는 DOM이 이벤트 핸들러에 내장되어있는 모든 기능을 수행합니다.

1 단계 :

는 구성 요소 코드는 속성 변경을 지원해야

<!DOCTYPE html> 
<html> 
    <head> 
    <meta charset="utf-8"> 
    <title>On-Event Test</title> 
    <script> 
    function onCheckHandler(event) { 
     console.log('onCheckHandler: %O', event); 
     event.stopPropagation(); 
     event.stopImmediatePropagation(); 
     //event.preventDefault(); 
    } 

    function eventListener(event) { 
     console.log('eventListener: %O', event); 
    } 
    (function() { 
     var template = `<div>Click to Check</div>`; 
     class MyEl extends HTMLElement { 
     constructor() { 
      super(); 

      var rootEl = this.attachShadow({mode: 'open'}); 
      rootEl.innerHTML = template; 
      rootEl.firstChild.addEventListener('click',() => { 
      var checkEvent = new CustomEvent("check", {bubbles:true,cancelable:true}); 
      if (this.dispatchEvent(checkEvent)) { 
       // Do default operation here 
       console.log('Performing default operation'); 
      } 
      }); 
      this._onCheckFn = null; 
     } 

     static get observedAttributes() { 
      return ['oncheck']; 
     } 

     attributeChangedCallback(attrName, oldVal, newVal) { 
      if (attrName === 'oncheck' && oldVal !== newVal) { 
      if (newVal === null) { 
       this.oncheck = null; 
      } 
      else { 
       this.oncheck = Function(`return function oncheck(event) {\n\t${newVal};\n};`)(); 
      } 
      } 
     } 

     get oncheck() { 
      return this._onCheckFn; 
     } 
     set oncheck(handler) { 
      if (this._onCheckFn) { 
      this.removeEventListener('check', this._onCheckFn); 
      this._onCheckFn = null; 
      } 

      if (typeof handler === 'function') { 
      this._onCheckFn = handler; 
      this.addEventListener('check', this._onCheckFn); 
      } 
     } 
     } 

     // Define our web component 
     customElements.define('my-el', MyEl); 
    })(); 
    </script> 
    </head> 
    <body> 
    <my-el oncheck="onCheckHandler(event)"></my-el> 
    </body> 
</html> 

것은이 두 단계를 필요로 작동하도록합니다.

속성이 문자열 (호출 할 함수)로 설정되면 코드는 속성 값으로 제공된 함수를 호출하려고하는 임시 함수를 만듭니다. 그 함수는 2 단계로 전달됩니다.

속성이 다른 것으로 설정되거나 속성이 제거되면 코드는 null을 2 단계로 전달합니다.

2 단계는 :

구성 요소 코드는 oncheck 속성을 지원해야합니다.

이 속성이 변경 될 때마다 removeEventListener을 호출하여이 속성에 대해 이전에 정의 된 이벤트 처리기를 제거해야합니다.

새 속성 값이 함수 인 경우 해당 함수를 처리기로 사용하여 addEventListener을 호출합니다.

알아 내기 재미있었습니다. 처음에는 DOM 기반의 oncheck 핸들러가 항상 처음이라고 생각했습니다. 그러나 onclickaddEventHandler('click')을 테스트하여 이벤트 핸들러가받은 순서대로 추가되었음을 알게되었습니다. DOM에 onclick이 제공된 경우 해당 이벤트 리스너가 먼저 추가됩니다. 그런 다음 removeAttribute('onclick')을 호출 한 다음 setAttribute('onclick', 'handler(event)')을 호출하면 해당 이벤트 핸들러가 목록의 끝으로 이동합니다.

따라서이 코드는 정확히 click 이벤트와 동일한 내용을 복제합니다.

관련 문제