【问题标题】:Web components: inheriting from DOM prototypesWeb 组件:从 DOM 原型继承
【发布时间】:2013-05-07 20:16:58
【问题描述】:

目前开发的 Web 组件规范的一部分是可以创建自己的 HTML 元素,例如通过调用新的document.register。这里给出一个例子:https://github.com/mozilla/web-components/blob/master/demo/demo.html

如您所见,一个新的x-bar 元素是通过从 HTML span 元素的原型继承其原型而创建的。

现在我在 Firefox Nightly 中尝试了以下操作(顺便说一下,支持 document.register):

var x = Object.create(HTMLInputElement.prototype);

我一直认为这将是扩展/自定义普通input 元素的行为或外观的第一步。

但是,当我运行 x.value 之类的东西时,浏览器的 Javascript 引擎会抛出 TypeError: Value does not implement interface HTMLInputElement

现在我有点卡住了。是当前实现还是规范的限制?

【问题讨论】:

  • 以下两个答案对我理解自定义元素如何扩展现有元素类型以及如何填充此行为非常有帮助。由于我只能接受一个答案,我不得不做出选择。我接受了 csuwldcat 的回答,因为他给了我 Firefox 的预发布版本实际上已损坏的提示(它的奇怪行为与我最初的问题基本归结为)。

标签: javascript html dom web-component


【解决方案1】:

Marc 遇到此问题的原因是,当您从 现有的原生元素 继承来创建新的自定义元素时,您需要使用 document.register(TAG_NAME, OPTIONS)extends 属性选项对象传递您想要继承的所需标签名称。

要使用新的本机继承自定义元素,在标记中以声明方式写出元素时,您需要使用is="" 语法 - 尽管使用 JS,这就像创建任何其他元素一样 - 示例如下。这是两个 polyfill,试一试,告诉我效果如何:Mozilla - https://github.com/mozilla/web-components/blob/master/src/document.register.js - Google: https://github.com/toolkitchen/CustomElements

定义和注册

document.register('x-input', {
  extends: 'input',
  prototype: Object.create(HTMLInputElement.prototype, { ... })
});

在 HTML 中的使用

<input is="x-input" />

通过 JavaScript/DOM 使用

document.createElement('x-input')

【讨论】:

  • 感谢您的意见!我目前正在尝试。您的代码适用于当前稳定版本的 Firefox 的 polyfill。然而,自带 document.register 的 Firefox 主干版仍然无法正常工作。 (我猜在这种情况下 polyfill 什么都不做,因为 document.register 已经存在了。)
  • 您的示例在 Chrome 28 中也可以使用 document.webkitRegister 并且没有任何 polyfill,这在最新的 Firefox 中看起来是不正确的实现。
  • @Marc 是的,在 Firefox 的预发布版本中提供的 document.register() 的早期实现已经过时并且不能正常工作 - 但很快就会更新(现在我们正在完成规范)。当您在 Firefox 预发布版本中打开 Web 组件的首选项时,它会添加 X-Tags 尝试使用的旧版本(作为 polyfill 应该使用的),结果显示为被破坏。但是,如果禁用它,我们的 document.register() polyfill 和 X-Tag 在 Firefox 中可以正常工作。
  • 说到完成规范,Daniel,当前版本dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/…似乎没有提到元素注册选项的“扩展”属性......还是我看错地方了?
  • 'extends' 选项是我们(Google 和 Mozilla 合作开发 Web 组件的人员)认为在其之前包含在自定义元素规范中的内容。没有这个,从现有原生元素继承的自定义元素的 polyfill 创建变得非常困难。
【解决方案2】:

我无法透露 document.register() 的 x-tags polyfill 的详细信息,但在本机实现中看起来是这样的:

<script>
  var XFooProto = Object.create(HTMLInputElement.prototype);

  // Define its JS API.
  XFooProto.showVal = function() {
    alert(this.value);
  };

  var XFoo = document.webkitRegister('x-foo', {prototype: XFooProto});

  var xfoo = document.createElement('input', 'x-foo');
  xfoo.value = 50;

  xfoo.addEventListener('click', function(e) {
    e.target.showVal();
  });

  document.body.appendChild(xfoo);   
</script>

example 在 Chrome Canary 28 中工作。您目前需要在about:flags 中翻转“启用实验性 WebKit 功能”标志才能获得document.webkitRegister()

我怀疑如果你用 FF polyfill 做类似的事情,事情可能会解决。如果您有兴趣使用 &lt;element&gt; 和/或使用其他 Web 组件规范创建自定义元素,也可以查看 https://github.com/toolkitchen 的 polyfill。

【讨论】:

  • 请注意,我的问题与 x-tags polyfill 本身无关;我只是用他们的演示代码来激发动力。
  • 我试过你的例子,它在 Firefox Trunk 中不起作用,因为 xfoo 只是一个普通的输入元素。事实上,在您的代码中,您正在创建 xfoo,并调用 createElement 接收“输入”作为其第一个参数。第二个参数 'x-foo' 不是因为 createElement 只为一个元素定义而被忽略了吗?
  • 好的,让您的示例在 Chrome 28 中运行,这显然尊重 document.createElement 的第二个参数。顺便说一句,这是在某个地方记录的吗?
  • 请忘记我的最后一个问题;在自定义元素草稿中找到了 createElement 的扩展。
猜你喜欢
  • 2017-07-06
  • 2016-02-15
  • 1970-01-01
  • 2015-07-07
  • 2013-05-20
  • 2010-09-28
  • 2018-02-21
  • 1970-01-01
相关资源
最近更新 更多