自定义 HTML 元素

2024-03-25

The HTML 规范 https://html.spec.whatwg.org/multipage/scripting.html#custom-elements描述了存储在中的几种元素自定义元素注册表.

  1. 内置元素如<a>由内置子类表示HTML元素 like HTML锚元素.
  2. 自主自定义元素,例如<my-element>其延伸HTMLElement并注册自定义元素注册表.
  3. 定制内置元素 https://w3c.github.io/webcomponents/spec/custom/#customized-built-in-element like <a is="my-link">它扩展了一个子类HTMLElement并使用is="customized-tag-name"来指定类。
  4. 遗留元素 https://html.spec.whatwg.org/multipage/scripting.html#customized-built-in-element-restrictions like <isindex>其延伸HTML未知元素
  5. 可定制的元素 https://w3c.github.io/webcomponents/spec/custom/#custom-elements-upgrades-examples可能由于脚本加载延迟而尚未注册。

有没有办法在运行时计算出元素属于哪个存储桶?


下面 [jsbin https://jsbin.com/ravanifugo/edit?html] 无需测试构造函数即可完成工作和管理"[native code]"但必须有一种更好的方法来判断元素是否是内置的。

//<script>

// https://w3c.github.io/webcomponents/spec/custom/#valid-custom-element-name
var VALID_CUSTOM_ELEMENT_NAME_REGEX = /^(?!(?:annotation-xml|color-profile|font-face|font-face(?:-(?:src|uri|format|name))?|missing-glyph)$)[a-z][a-z.0-9_\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u200C\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uDFFF\uF900-\uFDCF\uFDF0-\uFFFD]*-[\-a-z.0-9_\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u200C\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uDFFF\uF900-\uFDCF\uFDF0-\uFFFD]*$/;

function classify(el) {
  var name = el.localName;
  // TODO: are elements from a different document dealt with by that
  // document's CustomElementRegistry?
  // How do we get from a document to a CustomElementRegistry?
  // Maybe just assert el.ownerDocument === document?
  // Does that screw up elements from <template> content.
  if (customElements.get(name)) { return 'custom'; }
  // TODO: check that the value of is="..." is registered
  if (el.getAttribute('is')) { return 'custom-builtin'; }
  var ctor = el.constructor;
  if (ctor === HTMLUnknownElement) { return 'legacy'; }
  if (ctor === HTMLElement) {
    if (VALID_CUSTOM_ELEMENT_NAME_REGEX.test(name)) {
      return 'customizable';
    }
  }
  return 'builtin';
}


// A bunch of element names from MDN and elsewhere to test
var names = [
  "a", "abbr", "acronym", "address", "applet",
  "annotation-xml", "area",
  "article", "aside", "audio", "b", "base", "basefont", "bdi", "bdo",
  "bgsound", "big", "blink", "blockquote", "body", "br", "button",
  "canvas", "caption", "center", "cite", "code", "col", "colgroup",
  "command", "content", "data", "datalist", "dd", "del", "details",
  "dfn", "dialog", "dir", "div", "dl", "dt", "element", "em", "embed",
  "fieldset", "figcaption", "figure", "font", "footer", "form",
  "frame", "frameset", "h1", "h6", "head", "header", "hgroup", "hr",
  "html", "i", "iframe", "image", "img", "input", "ins", "isindex",
  "kbd", "keygen", "label", "legend", "li", "link", "listing", "main",
  "map", "mark", "marquee", "menu", "menuitem", "meta", "meter",
  "multicol", "nav", "nobr", "noembed", "noframes", "noscript",
  "object", "ol", "optgroup", "option", "output", "p", "param",
  "picture", "plaintext", "pre", "progress", "q", "rp", "rt", "rtc",
  "ruby", "s", "samp", "script", "section", "select", "shadow",
  "slot", "small", "source", "spacer", "span", "strike", "strong",
  "style", "sub", "summary", "sup", "table", "tbody", "td",
  "template", "textarea", "tfoot", "th", "thead", "time", "title",
  "tr", "track", "tt", "u", "ul", "var", "video", "wbr", "xmp",
  "isindex",  // Known legacy element
  "un-registered", "reg-istered"];  // Test custom / customizable

//</script><script>

class MyElement extends HTMLElement {
  constructor() {
    super();
  }
}

customElements.define('reg-istered', MyElement);

//</script><script>
var table = document.createElement('table');
document.body.appendChild(table);
var tbody = document.createElement('tbody');
table.appendChild(tbody);
function addRowForElement(el) {
  var tr = document.createElement('tr');
  tbody.appendChild(tr);
  var td0 = document.createElement('td');
  tr.appendChild(td0);
  td0.appendChild(document.createTextNode(el.outerHTML));
  var td1 = document.createElement('td');
  tr.appendChild(td1);
  td1.appendChild(document.createTextNode('' + classify(el)));
}
for (var i = 0, n = names.length; i < n; ++i) {
  addRowForElement(document.createElement(names[i]));
}
var customBi = document.createElement('input');
customBi.setAttribute('is', 'my-custom-input');  // Not yet registered.
addRowForElement(customBi);
//</script><style>td:first-child { font-family: monospace }</style>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自定义 HTML 元素 的相关文章

随机推荐