Javascript 用于webcomponents/自定义事件(JS)的基于HTML的事件侦听器

Javascript 用于webcomponents/自定义事件(JS)的基于HTML的事件侦听器,javascript,html,web-component,Javascript,Html,Web Component,TL;博士是否可以用HTML(而不是JS)为自定义事件定义事件侦听器? 基于此,我尝试做以下工作: <my-checkreport onclick="myFunction()" oncheck="myFunction1)" check="myFunction()" ></my-checkreport> 是否可以为HTML中的自定义事件附加事件侦听器?而无需任何JS代码?不可以。但是您可以在元素的构造函数中定义一个属性来获取元素属性并对其求值。比如说, con

TL;博士是否可以用HTML(而不是JS)为自定义事件定义事件侦听器?

基于此,我尝试做以下工作:

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

是否可以为HTML中的自定义事件附加事件侦听器?

而无需任何JS代码?不可以。但是您可以在元素的构造函数中定义一个属性来获取元素属性并对其求值。比如说,

constructor() {
    // Other code.
    const onCheckFunc = this.getAttribute('oncheck')
    this.addEventListener('check', () => eval(onCheckFunc))
    // Rest of your code.
}
EDIT:正如@Intervalia所提到的,您不应该在
构造函数中检查元素的属性。您可以在
connectedCallback
中执行此操作。但请记住:

  • 通常,工作应尽可能推迟到
    connectedCallback
    ,尤其是涉及获取资源或渲染的工作。但是,请注意,
    connectedCallback
    可以被多次调用,因此任何真正一次性的初始化工作都需要一个防护装置来防止它运行两次
  • 通常,应使用
    构造函数
    来设置初始状态和默认值,并设置事件侦听器,可能还有一个影子根

这是最接近模拟事件处理程序的DOM声明的方法。据我所知,这段代码完成了DOM为内置事件处理程序所做的一切

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

事件测试
函数onCheckHandler(事件){
日志('onCheckHandler:%O',事件);
event.stopPropagation();
事件。stopImmediatePropagation();
//event.preventDefault();
}
函数eventListener(事件){
日志('eventListener:%O',事件);
}
(功能(){
var template=`单击以检查';
类MyEl扩展了HtmleElement{
构造函数(){
超级();
var rootEl=this.attachShadow({mode:'open'});
rootEl.innerHTML=模板;
rootEl.firstChild.addEventListener('click',()=>{
var checkEvent=new CustomEvent(“检查”,{bubbles:true,cancelable:true});
if(此dispatchEvent(检查事件)){
//在此处执行默认操作
console.log(“执行默认操作”);
}
});
此参数为.\u onCheckFn=null;
}
静态get ObservedAttribute(){
返回['oncheck'];
}
attributeChangedCallback(属性名称、旧值、新值){
如果(attrName=='oncheck'&&oldVal!==newVal){
如果(newVal==null){
this.oncheck=null;
}
否则{
this.oncheck=函数(`returnfunctiononcheck(event){\n\t${newVal};\n};`)();
}
}
}
获取oncheck(){
将此返回。\u onCheckFn;
}
设置oncheck(处理程序){
如果(此项检查){
this.removeEventListener('check',this.\u onCheckFn);
此参数为.\u onCheckFn=null;
}
if(处理程序的类型=='function'){
这个。_onCheckFn=handler;
this.addEventListener('check',this.\u onCheckFn);
}
}
}
//定义我们的web组件
自定义元素。定义('my-el',MyEl);
})();
要实现这一点,您需要两个步骤:

第一步:

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

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

当该属性被设置为任何其他属性或该属性被删除时,代码会将空值传递到第二步

第二步:

组件代码必须支持
oncheck
属性

每当更改此属性时,它都需要通过调用
removeEventListener
删除以前为此属性定义的任何事件处理程序

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

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


因此,这段代码完全复制了我在
单击
事件中所做的事情。

也许这个答案可以帮助您:或者更可能的答案是:记住读取构造函数中的属性是违反Web组件规则的。不能检查元素的属性和子元素。。。
<!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>