9

我正在尝试创建一个可在表单元素中使用的 Web 组件,该组件具有namevalue. 我认识到我可以创建一个 Webextends组件HTMLInputElement

<input is="very-extended">

但我正在尝试创建一个全新的元素。

创建常规 Web 组件时,您可以从常规HTMLElement( HTMLElement.prototype) 的原型创建它。这使我假设我可以使用HTMLInputElement( HTMLInputElement.prototype) 的原型创建不同的元素。您实际上extending在输入元素的 API 时使用了该原型,那么为什么我不能使用该原型来创建一个在表单中工作的全新元素呢?

如果您查看常规输入字段的 shadow dom:

在此处输入图像描述

你可以看到里面有一个div。我知道这HTMLInputElement有方法和属性、getter/setter 等。那么为什么当我尝试创建我的组件时,它不能成为表单中名称、值对的一部分?

这是我如何尝试创建此 Web 组件的示例:

请注意,他应该在支持 Web 组件的浏览器中进行测试。

(function() {

  var iconDoc = (document._currentScript || document.currentScript).ownerDocument;
  var objectPrototype = Object.create(HTMLInputElement.prototype);

  Object.defineProperty(objectPrototype, 'name', {
    writable: true
  });

  Object.defineProperty(objectPrototype, 'value', {
    writable: true
  });

  objectPrototype.createdCallback = function() {
    var shadow = this.createShadowRoot();
    var template = iconDoc.querySelector('#test');
    shadow.appendChild(template.content.cloneNode(true));
  };

  document.registerElement('custom-input', {
    prototype: objectPrototype
  });

})();

console.log(
  $('form').serialize()
)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<template id="test">
  <div>This is a special input</div>
</template>

<form>
  <input name="regular" value="input">
  <custom-input name="foo" value="bar"></custom-input>
</form>

为什么在表单中找不到名称、值对,如何创建自定义表单元素?

4

3 回答 3

5

您可以创建<custom-input>将由 a 解释的自定义元素form,只需在您template隐藏 input元素中 添加namevalue配对您想要的。

<template>
    <input type="hidden" name="foo" value="defaultVal">
</template>

默认value(和name)可以由您的自定义元素内部逻辑更新。

这个隐藏的input 不能被插入到被容器检测到的 Shadow DOM 中form

(function() {

  var iconDoc = (document._currentScript || document.currentScript).ownerDocument;
  var objectPrototype = Object.create(HTMLInputElement.prototype);

  objectPrototype.createdCallback = function() {
    //var shadow = this.createShadowRoot();
    var template = iconDoc.querySelector('#test');
    this.appendChild(template.content.cloneNode(true));
  };

  document.registerElement('custom-input', {
    prototype: objectPrototype
  });

})();

console.log(
  $('form').serialize()
)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<template id="test">
  <input type="hidden" name="foo" value="bar">
</template>

<form>
  <input name="regular" value="input">
  <custom-input name="foo" value="bar"></custom-input>
</form>

于 2016-07-29T21:37:13.710 回答
3

凯夫博特,

您似乎认为该元素包含在表单中。事实并非如此。它是通过标签 name搜索其子元素的表单,以决定它应该包含哪些元素。它会简单地忽略那些标签名称未知的。

您的custom-input名字不在表单搜索的元素中。因此,它不包含在表格中。自定义元素的原型无关紧要。这就是为什么如果你使用它会起作用的原因is,因为那时标签名称被保留了。

当然custom-form,如果您愿意,您可以实现自己的行为不同的行为。

于 2016-07-28T17:16:03.207 回答
2

你可以这样做:

(function() {
  var newInputExtended = Object.create(HTMLInputElement.prototype);

  newInputExtended.createdCallback = function() {
    this.value = 'baz';
  };

  document.registerElement('foo-input', {
    extends: 'input',
    prototype: newInputExtended
  });
  
  
  window.something = function(form, event) {
    $('<p>')
    .text($(form).serialize())
    .appendTo('body')
  
    event.preventDefault();
  }
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form onsubmit="something(this, event)">
  <input is="foo-input" name="foo" value="bar">
  <button>Hi</button>
</form>

但是,如果您尝试创建新的影子根,则会出现错误。看起来您仅限于在元素的用户代理影子根周围扩展数据/逻辑。

于 2016-07-29T14:55:49.077 回答