MDN wants to learn about developers like you: https://qsurvey.mozilla.com/s3/MDN-dev-survey

自定义元素(Custom Elements)

自定义元素是一种用于创建自己的自定义HTML元素的功能。他们可以有自己的脚本行为和CSS样式。它们是Web组件的一部分,但也可以自己单独使用。

注意:自定义元素最近才稳定,并且MDN的某些部分仍包含来自旧规范草案的过时API的文档。

可能不清楚为什么创建新的自定义元素能力,毕竟现在已经可以创建一个标签名称像<mytag>, 并用CSS设置其样式,然后使用脚本给它附加行为。自定义元素的一个优势是它们的生命周期反应,这允许将行为附加到新元素的“生命周期”的不同部分。例如,当元素被插入到DOM中时 (“已连接”) 可以附加某个行为, 及当它从DOM中移除时 (“断开连接”) 或者 当其属性改变时, 附加不同的行为。

启用自定义元素关键在于 Document.registerElement() 方法,此方法向浏览器注册一个新元素,该元素默认使用 HTMLElement 接口(如果您创建了类似<mytag>的标签,但不注册,它将会使用 HTMLUnknownElement接口。您也可以在例如 <button> 这样的原生元素的基础上创建自定义元素,不过如此一来就不能使用自定义标签名,比如 <my-button> ,而要使用 <button is="my-button"> 这样的语法了)。

生命周期回调(Lifecycle callbacks)

自定义元素可以使用以下生命周期回调函数:

  • readyCallback - 元素初始化时执行
  • insertedCallback - 元素插入DOM时执行
  • removedCallback - 元素被移除DOM时执行
  • attributeChangedCallback - 元素的属性被增、删、改时执行

示例

以下示例演示如何使用 template,shadow DOM 和生命周期回调来创建一个工作时钟元素:

<element name="tick-tock-clock">
  <template>
    <span id="hh"></span>
    <span id="sep">:</span>
    <span id="mm"></span>
  </template>
  <script>
    var template = document.currentScript.parentNode.querySelector('template');

    function start() {
      this.tick();
      this._interval = window.setInterval(this.tick.bind(this), 1000);
    }
    function stop() {
      window.clearInterval(this._interval);
    }
    function fmt(n) {
      return (n < 10 ? '0' : '') + n;
    }

    ({
      readyCallback: function () {
        this._root = this.createShadowRoot();
        this._root.appendChild(template.content.cloneNode());
        if (this.parentElement) {
          start.call(this);
        }
      },
      insertedCallback: start,
      removedCallback: stop,
      tick: function () {
        var now = new Date();
        this._root.querySelector('hh').textContent = fmt(now.getHours());
        this._root.querySelector('sep').style.visibility =
            now.getSeconds() % 2 ? 'visible' : 'hidden';
        this._root.querySelector('mm').textContent = fmt(now.getMinutes());
      },
      chime: function () { … }
    });
  </script>
</element>

自定义元素可用 Object.prototypeShadowRoot 相关技巧创建,如下 jsfiddle 所示:

在ES2015中创建自定义元素的一种简单方法是:使用 "Class" 而非 "ProtoType" ,此时可以不使用 "ShadowRoot"。

HTML文件:

If nothing appeared below, then your browser not supporting Custom Elements.
<x-product data-name="Ruby" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/ruby.png" data-url="http://example.com/1"></x-product>
<x-product data-name="JavaScript" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/javascript.png" data-url="http://example.com/2"></x-product>
<x-product data-name="Python" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/python.png" data-url="http://example.com/3"></x-product>

JS文件:

// Create a new object based of the HTMLElement prototype
var XProductProto = Object.create(HTMLElement.prototype);

// Set up the element.
XProductProto.createdCallback = function() {
    // Create a Shadow Root
    var shadow = this.createShadowRoot();

    // Create a standard img element and set it's attributes.
    var img = document.createElement('img');
    img.alt = this.getAttribute('data-name');
    img.src = this.getAttribute('data-img');
    img.width = '150';
    img.height = '150';
    img.className = 'product-img';

    // Add the image to the Shadow Root.
    shadow.appendChild(img);

    // Add an event listener to the image.
    img.addEventListener('click', function(e) {
        window.location = this.getAttribute('data-url');
    });
  
    // Create a link to the product.
    var link = document.createElement('a');
    link.innerText = this.getAttribute('data-name');
    link.href = this.getAttribute('data-url');
    link.className = 'product-name';

            // Add the link to the Shadow Root.
    shadow.appendChild(link);
};

// Register the new element.
var XProduct = document.registerElement('x-product', {
    prototype: XProductProto
});

CSS文件:

下例使用的 ::Shadow 已被弃用(deprecated)。

body {
  background: #F7F7F7;
}

x-product {
  display: inline-block;
  float: left;
  margin: 0.5em;
  border-radius: 3px;
  background: #FFF;
  box-shadow: 0 1px 3px rgba(0,0,0,0.25);
  font-family: Helvetica, arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

x-product::shadow .product-img {
  cursor: pointer;
  background: #FFF;
  margin: 0.5em;
}

x-product::shadow .product-name {
  display: block;
  text-align: center;
  text-decoration: none;
  color: #08C;
  border-top: 1px solid #EEE;
  font-weight: bold;
  padding: 0.75em 0;
}

这是上例的可执行版本:

规范(Specification)

自定义元素在下列规范中定义:

规范 状态 评论
Unknown Unknown  

资源

文档标签和贡献者

 此页面的贡献者: NNNaix, xgqfrms-GitHub, jchnxu
 最后编辑者: NNNaix,