用于Web组件/自定义事件(JS)的基于HTML的事件侦听器 [英] HTML-based event listener for webcomponents/custom events (JS)

查看:142
本文介绍了用于Web组件/自定义事件(JS)的基于HTML的事件侦听器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TL; DR; 是否可以为自定义事件定义HTML(不是JS)事件监听器?

基于此 codepen ,我正在尝试执行以下操作:

Basing on this codepen, I'm trying to do the following:

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

其中,myFunction会执行一些console.log的操作,这些操作在浏览器控制台中可以看到.当然,对于以下定义的自定义事件,本机onlick起作用,但oncheckcheck都不起作用(源于上方的链接

where myFunction does some console.log stuff that I can see in the browser console. Native onlick works, of course, but neither oncheck nor check work, for the custom event defined below (source taken from above linked 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中的自定义事件附加事件侦听器?

Is it possible to attach event listeners for custom events in HTML?

推荐答案

这是我可以用来模拟事件处理程序的DOM声明的最接近的方法.据我所知,这段代码完成了DOM为内置事件处理程序所做的所有工作.

This is the closest I can come to emulating the DOM declaration of an event handler. This code does everything, from what I can tell, that the DOM does for built in event handlers.

<!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>

要使其正常工作,您需要执行两个步骤:

To get this to work you need two steps:

第一步:

组件代码必须支持属性更改.

The component code must support an attribute change.

当属性设置为字符串(要调用的函数)时,代码将创建一个临时函数,该临时函数尝试调用作为属性值提供的函数.然后,该功能将传递到第二步.

When the attribute is set to a string (The function to call) then the code creates a temporary function that attempts to call the function provided as the attribute value. That function is then passed on to step two.

当该属性设置为其他任何属性或删除该属性时,代码会将null传递给第二步.

When the attribute is set to anything else or the attribute is removed then the code passes a null on to step two.

第二步:

组件代码必须支持oncheck属性.

The component code must support the oncheck property.

无论何时更改此属性,都需要通过调用removeEventListener删除此属性的所有先前定义的事件处理程序.

Whenever this property is changed it needs to remove any previously defined event handler for this property by calling removeEventListener.

如果该属性的新值是一个函数,则使用该函数作为处理程序调用addEventListener.

If the new value of the property is a function then is calls addEventListener with that function as the handler.

这很有趣.起初,我认为基于DOM的oncheck处理程序将永远是第一个.但是通过测试onclickaddEventHandler('click'),我发现事件处理程序是按收到的顺序添加的.如果在DOM中提供了onclick,那么将首先添加该事件侦听器.如果然后依次调用removeAttribute('onclick')setAttribute('onclick', 'handler(event)'),则该事件处理程序将移至列表的末尾.

This was fun to figure out. At first I thought that the DOM based oncheck handler would always be first. But by testing onclick and addEventHandler('click') I discovered that the event handlers are added in the order received. If onclick is provided in the DOM than that event listener is added first. If you then call removeAttribute('onclick') and then setAttribute('onclick', 'handler(event)') then that event handler is moved to the end of the list.

所以这段代码完全复制了我与click事件相同的内容.

So this code replicates exactly what I same with the click event.

这篇关于用于Web组件/自定义事件(JS)的基于HTML的事件侦听器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆