编写Web组件类的ES5方式是什么?

时间:2017-08-18 02:34:45

标签: javascript ecmascript-6 web-component

要定义自定义Web组件,我们可以扩展ES6类以访问元素的生命周期反应

class HelloElement extends HTMLElement {
  // Monitor the 'name' attribute for changes.
  static get observedAttributes() {return ['name']; }

  // Respond to attribute changes.
  attributeChangedCallback(attr, oldValue, newValue) {
    if (attr == 'name') {
      this.textContent = `Hello, ${newValue}`;
    }
  }
}

// Define the new element
customElements.define('hello-element', HelloElement);

ES5的等效方式是什么?

4 个答案:

答案 0 :(得分:7)

根据您的评论,我认为您的意思是ES6 语法,并且允许支持自定义元素的浏览器也支持ES6定义的功能。

要模拟调用super()的默认ES6构造函数,我们可以使用Reflect.construct来调用HTMLElement构造函数,但使用我们的HelloElement遍历器中的原型。

对于继承,您需要将.prototype构造函数的HelloElement设置为HTMLElement的实例,并在其上定义方法和属性。通常使用use Object.create()来创建一个非功能性的虚拟实例,而不需要在这里调用构造函数。

您可以使用Object.definePropertyobservedAttributes定义静态getter,但它通常只是一个静态列表,您只需将HelloElement.observedAttributes设置为属性名称数组即可。

function HelloElement() {
   return Reflect.construct(HTMLElement, [], HelloElement);
}
HelloElement.prototype = Object.create(HTMLElement.prototype);

// Monitor the 'name' attribute for changes.
Object.defineProperty(HelloElement, 'observedAttributes', {
  get: function() { return ['name']; }
});
// or just use HelloElement.observedAttributes = ['name']
// if it doesn't need to be dynamic

// Respond to attribute changes.
HelloElement.prototype.attributeChangedCallback = function(attr, oldValue, newValue) {
  if (attr == 'name') {
    this.textContent = `Hello, ${newValue}`;
  }
}

customElements.define('hello-element', HelloElement);

setTimeout(function() {
  document.getElementById('example').setAttribute('name', "World");
}, 1000);
<hello-element id="example"></hello-element>

答案 1 :(得分:1)

没有ES5编写Web组件类的方法。 Web components require ES6 features,没有办法解决这个问题。如果您不能使用ES6 class语法,因为您的转换器没有发出,您至少需要使用ES6 Reflect.construct来创建具有您自己的原型的自定义元素。

或者,custom elements polyfill appears to work with ES5 classes,至少在大多数浏览器中都是如此。

答案 2 :(得分:0)

对于ECMAScript 5而言,它并没有真正有效地工作,而对于DOM节点来说,它更低效。如果您愿意,可以添加到主机原型中,但是您不会得到一个实际的,干净的子类。

这就是有时将对象包装器用于DOM元素的原因。

答案 3 :(得分:0)

您可以使用Reflect方法来执行此操作,但这是ES6的功能。

function CustomElement() {
    return Reflect.construct(HTMLElement, [], CustomElement);
}
Object.setPrototypeOf(CustomElement.prototype, HTMLElement.prototype);
Object.setPrototypeOf(CustomElement, HTMLElement);

customElements.define('custom-element', CustomElement);
var elem = document.createElement('custom-element');
document.body.appendChild(elem);

这会将<custom-element></custom-element>附加到body