创建 Web 组件时出错

Error creating a Web component

我是 Web 组件的新手,我正在尝试创建一个非常简单的组件来了解它的工作原理。但是我在创建一个时遇到了问题。我按照两个 chrome and Mozilla 文档中提到的步骤进行操作,但我仍然无法成功创建一个,也找不到问题所在。

class toolTip extends HTMLElement {
  var msg = this.getAttribute('msg');
  var value = this.getAttribute('value');
  console.log(msg);
  console.log(value);
  this.innerHTML = msg + ' - ' + value;
}

customElements.define('mdm-tooltip', toolTip);
<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
  <meta charset="utf-8">
  <title>Web Components</title>
</head>

<body>
  <mdm-tooltip value='1st tooltip' msg='this the 1st tooltip created using WC'></mdm-tooltip>
  <mdm-tooltip value='2nd tooltip' msg='I replaced the existing text'>Im the existing text</mdm-tooltip>
</body>
<script src="main.js" defer></script>

</html>

这是浏览器抛出的错误, 我是 运行 这个代码在 Chrome V67.0.3396.99

在 class 中,您需要定义实际包含可执行代码的方法。在您的情况下,您的代码看起来很像初始化代码,因此构造函数似乎是合适的。

class ToolTip extends HTMLElement {
    constructor() {
        var msg = this.getAttribute('msg');
        var value = this.getAttribute('value');
        console.log(msg);
        console.log(value);
        this.innerHTML = msg + ' - ' + value;
    }
}

customElements.define('mdm-tooltip', ToolTip);

此外,JavaScript 中的命名约定之一是 classes 应该是 pascal 大小写(以大写字母开头)。

J.P。 10 Berge大部分是正确的。但是...根据 Web 组件构造函数的规则,您不能也不应该做几件事:

https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-conformance

4.13.2 Requirements for custom element constructors

When authoring custom element constructors, authors are bound by the following conformance requirements:

  • A parameter-less call to super() must be the first statement in the constructor body, to establish the correct prototype chain and this value before any further code is run.

  • A return statement must not appear anywhere inside the constructor body, unless it is a simple early-return (return or return this).

  • The constructor must not use the document.write() or document.open(type, replace) methods.

  • The element's attributes and children must not be inspected, as in the non-upgrade case none will be present, and relying on upgrades makes the element less usable.

  • The element must not gain any attributes or children, as this violates the expectations of consumers who use the createElement or createElementNS methods.

In general, work should be deferred to connectedCallback as much as possible—especially work involving fetching resources or rendering. However, note that connectedCallback can be called more than once, so any initialization work that is truly one-time will need a guard to prevent it from running twice.

In general, the constructor should be used to set up initial state and default values, and to set up event listeners and possibly a shadow root.

将代码移动到 connectedCallback 是一个更好的计划:

class ToolTip extends HTMLElement {
  connectedCallback() {
    var msg = this.getAttribute('msg');
    var value = this.getAttribute('value');
    console.log(msg);
    console.log(value);
    this.innerHTML = msg + ' - ' + value;
  }
}

customElements.define('mdm-tooltip', ToolTip);
<mdm-tooltip msg="help me" value="10"></mdm-tooltip>

不过你也可以改成这样:

class ToolTip extends HTMLElement {
  constructor() {
    super();
    this._msg = '';
    this._value = '';
  }
  
  static get observedAttributes() {
    return [ 'value', 'msg' ];
  }

  connectedCallback() {
    this._render();
  }
  
  attributeChangedCallback(attr, oldVal, newVal) {
    if (oldVal !== newVal) {
      this['_'+attr] = newVal; // This will set either `this._msg` or `this._value`
      this._render();
    }
  }
  
  _render() {
    this.innerHTML = `${this._msg} - ${this._value}`;
  }
}

customElements.define('mdm-tooltip', ToolTip);

setTimeout(() => {
  var el = document.querySelector('mdm-tooltip');
  el.setAttribute('value', 'Free');
  el.setAttribute('msg', 'I like getting stuff for');
}, 1000);
<mdm-tooltip msg="Help Me" value="10"></mdm-tooltip>

在此示例中,我们使用 observedAttributesattributeChangedCallback 来查看 valuemsg 属性何时更改。当他们这样做时,我们会重新渲染组件。

您还可以在设置值时使用属性:

class ToolTip extends HTMLElement {
  constructor() {
    super();
    this._msg = '';
    this._value = '';
  }
  
  static get observedAttributes() {
    return [ 'value', 'msg' ];
  }

  connectedCallback() {
    this._render();
  }
  
  attributeChangedCallback(attr, oldVal, newVal) {
    if (oldVal !== newVal) {
      this['_'+attr] = newVal; // This will set either `this._msg` or `this._value`
      this._render();
    }
  }
  
  get msg() {
    return this._msg;
  }
  set msg(val) {
    if (this._msg !== val) {
      this._msg = val;
      this._render();
    }
  }

  get value() {
    return this._value;
  }
  set value(val) {
    if (this._value !== val) {
      this._value = val;
      this._render();
    }
  }
  
  
  _render() {
    this.innerHTML = `${this._msg} - ${this._value}`;
  }
}

customElements.define('mdm-tooltip', ToolTip);

var el = document.createElement('mdm-tooltip');
el.value = 10;
el.msg = 'Five times two equals';
document.querySelector('.here').append(el);

setTimeout(() => {
  var el = document.querySelector('mdm-tooltip');
  el.value = [1,2,3];
  el.msg = 'I like getting stuff for';
}, 2000);
<div class="here"></div>

在此示例中,我为 valuemsg 添加了属性。现在,不必使用 setAttribute,您现在可以直接设置属性,并且属性不需要像属性那样是字符串。