CustomElementsV0:如何正确扩展原生 HTML 元素?

CustomElementsV0: How to properly extend a native HTML element?

我想创建一个扩展 HTMLInputElement 的 HTML 自定义元素,并为焦点、更改、单击、按键等事件定义其默认行为。

放弃 CustomElementV1(super() 调用产生 "Illegal constructor" 错误)后,我尝试使用 CustomElementV0 方法:

var Xinput = Object.create(HTMLInputElement.prototype);
Xinput.createdCallback = ()=>{
  this.addEventListener('change',(e)=>{
    console.info("field changed", e.target);
  });
};
var Xi = document.registerElement('x-input', { prototype: Xinput, extends: 'input'});

稍后创建节点:

var n = new Xi();

我本以为createdCallback函数中的this变量是指在做"new Xi()"时已经创建的DOM节点。但是,它引用了 Window 对象,因此,更改事件会被多次注册并为每个创建的元素触发一次:更改单个字段将触发更改事件的次数与 DOM.

中的 x-input 元素一样多

我在 Chrome v54 - v57 中观察到这种行为。

实现预期行为(即事件仅触发一次)的正确方法是什么?

正如评论中 link 所建议的,您不应使用箭头函数来定义 createdCallback 方法,因为它不会更改 this 值。

而是使用 "classical" function() 语法:

Xinput.createdCallback = function () {
  this.addEventListener('change',e=>
    console.info("field changed", e.target)
  );
};