最佳实践:通过HTML id或name属性访问表单元素?


136

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

<form name="myForm">  
    <input type="text" name="foo" id="foo" />

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

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

方法[1]和[3]在Mozilla Gecko文档中有详细记录,但都不是理想的方法。[1]太笼统而无用,[3]需要ID和名称(假设您将数据发布到服务器端语言)。理想情况下,最好只具有一个id属性或一个name属性(两者都有些多余,特别是如果id对于任何CSS都是不必要的,并且会增加输入错误的可能性等)。

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

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

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


我想这可以归结为我正在寻找最符合标准的方式来使用name属性访问表单元素...
seth 2010年

4
“同时拥有两者在某种程度上是多余的,特别是如果id对于任何CSS而言都不是必需的,并且会增加输入错误的可能性”-ID是有效使用标签所必需的。不只是CSS。

有时,网页上有多种形式,id属性可能会冲突。
Calmarius 2014年

Answers:


96

仅给您的表单一个ID,并仅输入一个名称

<form id="myform">
  <input type="text" name="foo">

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

document.getElementById("myform").elements["foo"]

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


1
@Karl ...您要达到什么目的?除了将JS内联到HTML中这样的事实(通常是效率低下的,因为它会在代码周围创建包装函数)之外,您总是返回false意味着您的表单将永远不会提交。因此,除非该表单不是要提交的(可能完全由JS代码使用),或者除非myFunc(this)通过AJAX提交(并且您不关心定期提交作为回退,以防AJAX)失败),...那么你就犯了一个错误。
2016年

1
通常情况下,只提交有效的表单数据,你会怎么做: myform.onsubmit = validateForm;(其中myForm会是一个变量引用窗体元素,validateForm是你的验证函数的名称...但你可以将其命名myFunc的,如果你真的真的想)。重要的一点是,每当表单无效时,validateForm()都应返回false,并向用户指示问题字段。当表单数据正确验证时,它应该返回true,这将允许进行提交操作。
2016年

2
避免在表单字段中使用id的另一个原因是:如果您想要同一表单(在同一页面中)的多个实例。
koriander

1
@João也可以使用,只要 “ foo”作为javascript属性名称有效即可。(可能不是-HTML5对name属性的值几乎没有任何限制,例如,您可以使用<select name="a+b"><input type="text" name="...2">,而不能使用javascript .propertyName表示法来引用它)。显式[]表示法还允许从表达式构建名称,例如myCheckBox = document.getElementById("myform").elements["CHK"+i]。另外,从风格上讲,我认为[]更好-它表明这些不仅仅是javascript对象的属性。YMMV。
Doin

1
关于棉绒,请记住,棉绒仅是样式指南,而棉绒“错误”并不意味着您的JavaScript无效或不正确。但是,在这种特殊情况下,插入规则的意思是“引用javascript对象属性时首选点标记”。那是个好主意,我一般建议您这样做。 但是,当linter没有意识到这一点时,elements它不是普通的JS对象,elements.foo或者elements["foo"]实际上已经转换为elements.namedItem(“ foo”)。也就是说,您正在调用DOM定义的函数,而不是引用JS属性!
Doin

34

[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是更可取的。


我碰巧看了道格拉斯·克罗克福德(Douglas Crockford)视频,他在这个主题上加了分。兴趣点是在-12:00。总结一下:

  • 文档集合(document.anchor,document.form等)已过时且不相关(方法1)。
  • name属性用于命名事物,而不是访问它们。它用于命名诸如窗口,输入字段和锚标记之类的东西。
  • “ ID是用来唯一标识元素以便可以访问它的东西。它们(名称和ID)曾经是可互换的,但现在不再可用。”

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


2
那么这只是一个hack吗?document.getElementById(“ myform”)。foo; 在对DOM进行了相当多的研究之后,我不清楚为什么它甚至可以工作。我的猜测是表单对象也是在html name属性上索引的子元素数组……
seth 2010年

1
您还提到“该名称未作为POST / GET的一部分传递给服务器,并且不适用于哈希样式书签”。这不就是IS传递给服务器的信息吗?使用PHP时,name属性是$ _POST全局索引。
赛斯

2
@Justin,这是传递给服务器的name属性。
阿努拉格

2
@seth较早的DOM规范似乎对为什么document.aForm.foo有效非常含糊,但HTML5规范似乎清楚地定义了HTMLFormElement具有的接口caller getter any namedItem(in DOMString name);。更多内容,请访问whatwg.org/specs/web-apps/current-work/multipage/…–
Anurag

1
@你们两个:“ ...将name属性应用于表单时是没有用的...”我不是在谈论inputor 的name属性select,而是在谈论的name属性form。a的name属性form 不会传递到服务器。
贾斯汀·约翰逊

14

要访问放置在表单中的命名元素,优良作法是使用form对象本身。

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


8
您是什么意思“使用表单对象本身”?拥有表单对象后,您将使用哪种方法访问特定元素?
赛斯

2
我的意思是我建议使用N5(document.getElementById('myForm')。elements.foo)访问命名项,使用N6(document.getElementById('myForm')。elements)访问元素的可迭代集合
Sergey Ilinsky

我正在定义我的代码的样式...并且作为一种偏好,我坚持使用ID ....那样,元素访问在整个页面中是一致的。+提及的其他原因。

1
为什么使用getElementID访问表单是一种好习惯?为什么document.myForm不起作用?(我遇到了无法正常工作的情况,我想知道为什么)
Spundun

嘿,Spundun,您可能在几个月前解决了您的问题(或者您举起了手:)),但是如果您想知道,那可能是由于您没有为表单HTML元素提供“名称”属性。
谢尔顿·R.

8

我非常喜欢第五种方法。即
[5]使用特殊的JavaScript标识符将此表单或字段对象从事件处理程序传递给函数。

具体来说,对于表格:

<form id="form1" name="form1" onsubmit="return validateForm(this)">

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

使用此技术,函数将永远 不必知道
-页面中定义表单的顺序,
-表单ID或
-表单名称

同样,对于字段:

<input type="text" name="maxWeight">
...
<input type="text" name="item1Weight" onchange="return checkWeight(this)">
<input type="text" name="item2Weight" onchange="return checkWeight(this)">

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;
}

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


不确定根本原因是什么,但是在某些(但不是全部)情况下,我有这种方法返回空字符串。
Jacob Lee

7

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

[3]同时需要一个id和一个名称...两者都有些多余

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

<label for="foo">Foo:</label>
<input type="text" name="foo" id="foo" />

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

这有点多余,但是当您具有复选框/单选按钮(其中几个可以共享一个)时,则显得有些多余name。最终,idname用于不同的目的,即使两者通常设置为相同的值。


5
如果将输入包装在其标签中,则不需要id或for属性。<label> Foo:<input type =“ text” name =“ foo” </ label>
肯尼伯(Kennebec)2010年

3
非常正确,尽管那确实限制了您在外观和感觉上可以达到的目标。
Paul D. Waite,2010年

2
@kennebec-如果希望标签与元素关联,则应始终使用id。如果没有匹配的forid属性,则较旧版本的IE(<8?)不会将标签内的元素与标签相关联。
RobG 2012年

除了@kennebec编写的内容外,使用ID还会创建JS全局变量,应避免使用。
mikemaccana 2014年

1
@mikemaccana:我之前已经看到引起问题的原因。我确实认为,如果您的ID具有合理的描述性,并且您的JavaScript具有合理的命名空间,则不太可能引起问题。
Paul D. Waite

6

这有点旧,但我想补充一点我认为相关的内容。
(我的意思是评论对上述一个或2个线程,但它似乎我需要的声誉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>

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

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


起作用的是 document.forms.mainForm.R1.value,这确实是避免使用难看且乏味的类型的好方法document.getElementById()
Kai Carver

2

老式的我一直使用'document.myform.myvar'语法,但是最近我发现它在Chrome中失败(Firefox和IE中的OK)。这是一个Ajax页面(即加载到div的innerHTML属性中)。也许Chrome无法将表单识别为主要文档的元素。我改用了getElementById(没有引用表单),它工作正常。


您可以插入.forms,所以 document.forms.myform.myvar
Kai Carver,

1

只是为了增加已经说过的内容,您可以使用或最好使用Object形式的属性来访问inputs ,因为没有它,您可能会获得名为“ foo”的形式的属性,而不是HTML元素。根据@Paul D. Waite的说法,同时具有名称和ID是完全可以的。nameidelements

var myForm = document.getElementById("myform")
console.log(myForm.foo.value) // hey
console.log(myForm.foo2.value) // hey
//preferable
console.log(myForm.elements.foo.value) // hey
console.log(myForm.elements.foo2.value) // hey
<form id="myform">
  <input type="text" name="foo" id="foo2" value="hey">
</form>

根据HTMLFormElement.elements页面上的MDN

HTMLFormElement属性元素返回一个HTMLFormControlsCollection,其中列出了该元素中包含的所有表单控件。独立地,您可以使用length属性仅获取表单控件的数量。

您可以使用索引或元素的名称id来访问返回的集合中的特定表单控件。


1

name领域运作良好。它提供了对的引用elements

parent.children-将列出所有带有父级名称字段的元素。 parent.elements-仅列出form elements诸如input-text, text-area, etc

var form = document.getElementById('form-1');
console.log(form.children.firstname)
console.log(form.elements.firstname)
console.log(form.elements.progressBar); // undefined
console.log(form.children.progressBar);
console.log(form.elements.submit); // undefined
<form id="form-1">
  <input type="text" name="firstname" />
  <input type="file" name="file" />
  <progress name="progressBar" value="20" min="0" max="100" />
  <textarea name="address"></textarea>
  <input type="submit" name="submit" />
</form>

注意:.elements要正常工作,parent需要将<form> tag。而,.children将适用于HTML-element- <div>, <span>, etc

祝好运...


0

表格2可以,建议使用表格3。
名称和ID之间的冗余是出于保持兼容性的需要,在html 5上,某些元素(如img,form,iframe等)将失去其“名称”属性,建议从现在开始仅使用其id来引用它们上 :)


由于服务器端语言使用输入元素的方式,输入元素似乎永远不会丢失其name属性。因此,问题仍然存在,如果仅设置了name属性,符合标准的方法是什么?
赛斯

在符合标准的开发中,对于初学者来说,您不仅会拥有名称。如果您真的没有ID,则建议使用document.getElementByName()函数。
wintermute 2010年

0

为了补充其他答案,document.myForm.foo是所谓的DOM级别0,这是Netscape实施的方式,因此即使大多数浏览器都支持,它也不是真正的开放标准。


4
通过名称,ID和索引访问表单和表单控件是HTML集合的DOM 2 HTML标准的一部分。
RobG 2012年

0

签出此页面:https : //developer.mozilla.org/En/DOM/Document.getElementsByName

document.getElementsByName('foo')[0]; // returns you element.

它必须是“元素”,并且必须返回一个数组,因为多个元素可能具有相同的名称。


@robert,我现在认为这可能是一个不错的解决方案,尽管文档直接使我感到紧张:“鉴于上述文档类型和当前非标准行为之间的上述变化,该方法的使用可能存在疑问XHTML中的方法。”
塞思2010年

嗨,您好。哪个文档建议这样做?我认为,如果您正在工作的所有DOM环境中都使用xhtml,那么您应该可以。另外,哪些浏览器不支持此功能?这是IE的文档:msdn.microsoft.com/en-us/library/ms536438(VS.85).aspx除了上面的Mozilla,还有谁可能不支持它?
罗伯特

0

对于确切的问题,我的回答将有所不同。如果我想专门访问某个元素,那么我将使用document.getElementById()。一个例子是计算一个人的全名,因为它基于多个字段,但这是一个可重复的公式。

如果我想作为功能结构(表单)的一部分访问元素,那么我将使用:

var frm = document.getElementById('frm_name');
for(var i = 0; i < frm.elements.length;i++){
   ..frm.elements[i]..

从业务的角度来看,这也是它的工作方式。循环内的更改与应用程序中的功能更改一起进行,因此有意义。我主要将其应用于用户友好的验证并防止网络调用检查错误的数据。我重复验证服务器端(并向其中添加更多内容),但是如果我可以帮助用户客户端,那么这对所有人都有益。

对于数据聚合(例如根据表单中的数据构建饼图),我使用配置文档和定制的Javascript对象。然后,该字段的确切含义与其上下文有关很重要,我是否使用document.getElementById()。



-1

我喜欢这个

document.forms['idOfTheForm'].nameOfTheInputFiled.value;

2
欢迎使用SO,感谢您的投入。请编辑您的答案,并解释原因和方式。
B–rian
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.