最佳实践:按HTML ID或名称属性访问表单元素?

set*_*eth 130 html javascript forms dom

正如任何经验丰富的JavaScript开发人员所知,有很多(太多)方法可以做同样的事情.例如,假设您有一个文本字段,如下所示:

<form name="myForm">  
    <input type="text" name="foo" id="foo" />
Run Code Online (Sandbox Code Playgroud)

在JavaScript中有很多方法可以访问它:

[1]  document.forms[0].elements[0];
[2]  document.myForm.foo;
[3]  document.getElementById('foo');
[4]  document.getElementById('myForm').foo;
     ... and so on ...
Run Code Online (Sandbox Code Playgroud)

方法[1]和[3]在Mozilla Gecko文档中有详细记载,但都不是理想的.[1]过于笼统而无用,[3]同时需要id和名称(假设您将数据发布到服务器端语言).理想情况下,最好只有一个id属性或一个name属性(两者都有点多余,特别是如果id不是任何css所必需的,并且增加了拼写错误的可能性等).

[2]似乎是最直观的,它似乎被广泛使用,但我没有看到它在Gecko文档中引用,我担心向前兼容性和跨浏览器兼容性(当然我想成为尽可能符合标准).

那么这里最好的做法是什么?任何人都可以指出DOM文档或W3C规范中可以解决此问题的内容吗?

注意我对非库解决方案(jQuery/Prototype)特别感兴趣.

Doi*_*oin 91

仅为您的表单提供ID,并且您的输入仅为名称:

<form id="myform">
  <input type="text" name="foo">
Run Code Online (Sandbox Code Playgroud)

然后,访问输入元素的最符合标准且问题最少的方法是:

document.getElementById("myform").elements["foo"]
Run Code Online (Sandbox Code Playgroud)

使用.elements["foo"]而不是just .foo更可取,因为后者可能返回名为"foo"的形式的属性而不是HTML元素!

  • 这是非常合理的答案! (6认同)
  • @João 也可以,*提供*“foo”作为 javascript 属性名称是有效的。(可能不是 - HTML5 对 `name` 属性的值几乎没有限制,因此例如您可以使用 `&lt;select name="a+b"&gt;` 或 `&lt;input type="text" name=" ...2"&gt;`,无法使用 javascript .propertyName 表示法引用)。显式 [] 表示法还允许从表达式构建名称,例如 `myCheckBox = document.getElementById("myform").elements["CHK"+i]`。另外,从风格上来说,我认为 [] 更好——它清楚地表明这些不仅仅是 javascript 对象的属性。YMMV。 (4认同)
  • 避免在表单字段中使用 id 的另一个原因是:如果您想要同一表单的多个实例(在同一页面中)。 (2认同)

Jus*_*son 33

[1] document.forms [0] .elements [0];

当我看到这种元素访问方法时,脑海中浮现出 " No-omg-never! ".这样的问题在于它假设DOM是普通数据结构(例如:数组),其中元素顺序无论如何都是静态的,一致的或可靠的.我们知道99.9999%的时间,事实并非如此.input在表单中重新排序或元素,在相关表单form之前向页面添加另一个元素,或移动相关表单都是此代码中断的所有情况.短篇小说:这很脆弱.一旦你添加或移动某些东西,它就会破裂.

[2] document.myForm.foo;

我和Sergey ILinsky在一起:

  • 通过引用其id属性来访问任意元素:document.getElementById("myform");
  • 按名称访问命名表单元素,相对于其父表单元素: document.getElementById("myform").foo;

我使用此方法的主要问题是该name属性在应用于表单时无用.该名称不作为POST/GET的一部分传递给服务器,并且不适用于散列样式书签.

[3] document.getElementById('foo');

在我看来,这是最好的方法.直接访问是最简洁明了的方法.

[4] document.getElementById('myForm').foo;

在我看来,这是可以接受的,但比必要的更冗长.方法#3是优选的.


我恰巧正在观看道格拉斯·克罗克福德的一段视频,并且他正在考虑这个问题.兴趣点在-12:00.总结一下:

  • 文档集合(document.anchor,document.form等)已过时且无关紧要(方法1).
  • name属性用于命名事物,而不是访问它们.它用于命名窗口,输入字段和锚标记等内容.
  • "你应该使用ID来唯一地标识一个元素,以便你可以访问它.它们(名称和ID)曾经是可以互换的,但它们已经不存在了."

所以你有它.从语义上讲,这是最有意义的.

  • 那么这只是一个黑客吗?document.getElementById("myform").foo; 在对 DOM 进行了相当多的研究后,我不清楚为什么这甚至有效。我的猜测是表单对象也是在 html name 属性上索引的它的子元素的数组...... (2认同)
  • 您还提到“名称不会作为 POST/GET 的一部分传递到服务器,并且不适用于哈希样式书签”。这不正是传递给服务器的内容吗?当您使用 PHP 时,name 属性是 $_POST 全局中的索引。 (2认同)
  • @Justin,它是传递给服务器的name属性. (2认同)
  • @seth 旧的 DOM 规范对于`document.aForm.foo` 的工作原理似乎很模糊,但 HTML5 规范似乎清楚地定义了 `HTMLFormElement` 的接口,它具有 `caller getter any namedItem(in DOMString name);`。更多信息请访问 http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#the-form-element (2认同)
  • @你们俩:“...名称属性在应用于表单时毫无用处...”我不是在谈论`input`或`select`的名称属性,我正在谈论名称属性的“形式”。“表单”的名称属性*不会*传递到服务器。 (2认同)

Ser*_*sky 14

要访问放置在表单中的命名元素,最好使用form对象本身.

要访问DOM树中的任意元素(有时可能在表单中找到),请使用getElementById和元素id.

  • 你是什​​么意思"使用表单对象本身"?获得表单对象后,您使用什么方法来访问特定元素? (8认同)
  • 我的意思是我建议使用N5(document.getElementById('myForm').elements.foo)来访问命名项目和N6(document.getElementById('myForm').elements)来访问可迭代的元素集合 (2认同)

Rob*_*ond 8

我更喜欢第五种方法.即
[5]使用特殊的JavaScript标识符窗体或字段对象传递给从事件处理程序的功能.

具体来说,对于表格:

<form id="form1" name="form1" onsubmit="return validateForm(this)">
Run Code Online (Sandbox Code Playgroud)

// The form validation function takes the form object as the input parameter
function validateForm(thisForm) {
  if (thisform.fullname.value !=...
Run Code Online (Sandbox Code Playgroud)

使用这种技术,函数永远 不必知道
- 页面中定义表单的顺序,
- 表单ID,还是
表单名称

同样,对于字段:

<input type="text" name="maxWeight">
...
<input type="text" name="item1Weight" onchange="return checkWeight(this)">
<input type="text" name="item2Weight" onchange="return checkWeight(this)">
Run Code Online (Sandbox Code Playgroud)

function checkWeight(theField) {
  if (theField.value > theField.form.maxWeight.value) {
    alert ("The weight value " + theField.value + " is larger than the limit");
    return false;
  }
return true;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,函数永远不必知道特定权重字段的名称或ID,但它确实需要知道权重限制字段的名称.


Pau*_*ite 7

它并没有真正回答你的问题,只是在这一部分:

[3]需要一个id和一个名字......两者都有点多余

您最有可能需要id在每个表单字段上都有一个属性,以便您可以将其<label>元素与它相关联,如下所示:

<label for="foo">Foo:</label>
<input type="text" name="foo" id="foo" />
Run Code Online (Sandbox Code Playgroud)

这是可访问性所必需的(即如果你不关联表单标签和控件,为什么你这么讨厌盲人?).

这有点多余,虽然当你有复选框/单选按钮时会少一些,其中有几个可以共享一个name.最终,id并且name用于不同的目的,即使两者通常设置为相同的值.

  • 如果在其标签中包装输入,则不需要id或for属性.<label> Foo:<input type ="text"name ="foo"</ label> (5认同)
  • 非常正确,尽管这确实限制了您在外观和感觉方面可以实现的目标。 (3认同)
  • @ kennebec-如果你想让标签与一个元素相关联,你应该总是使用一个id.较旧版本的IE(<8?)如果没有匹配*for*和*id*属性,则不会将标签内的元素与标签相关联. (2认同)

VSi*_*Sim 5

这有点旧,但是我想补充一点我认为相关的东西。
(我打算在上面的一个或两个线程上发表评论,但似乎我需要信誉50,而在撰写本文时,我只有21。:))
只是想说,有时候访问访问更好表单中的元素按名称而不是ID。我不是在谈论表格本身。表单,确定,您可以为其指定一个ID,然后通过它进行访问。但是,如果您在表单中有一个单选按钮,则将其作为单个对象使用(获取和设置其值)要容易得多,据我所知,只能按名称进行此操作。

例:

<form id="mainForm" name="mainForm">
    <input type="radio" name="R1" value="V1">choice 1<br/>
    <input type="radio" name="R1" value="V2">choice 2<br/>
    <input type="radio" name="R1" value="V3">choice 3
</form>
Run Code Online (Sandbox Code Playgroud)

您可以通过使用
document.mainForm.R1.value

document.getElementById(“ mainForm”)。R1.value 来获取/设置单选按钮R1的整体检查值。
因此,如果您想使用单一样式,可以希望始终使用此方法,而不管表单元素的类型如何。我,我很舒服地按名称访问单选按钮,按ID访问文本框。