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

Posted

技术标签:

【中文标题】最佳实践:通过 HTML id 或 name 属性访问表单元素?【英文标题】:Best Practice: Access form elements by HTML id or name attribute? 【发布时间】:2011-01-26 23:46:25 【问题描述】:

任何经验丰富的 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 属性访问表单元素... "两者兼有有些多余,尤其是在任何 css 都不需要 id 的情况下,并且增加了拼写错误的可能性" -- ID 是有效使用标签所必需的。不仅仅是 CSS。 有时网页上有多个表单,id属性可能会发生冲突。 【参考方案1】:

只给你的表单一个id,你的输入一个name

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

那么,访问您的输入元素最符合标准且问题最少的方式是通过:

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

最好使用.elements["foo"] 而不是.foo,因为后者可能会返回名为“foo”而不是html 元素的属性!

【讨论】:

@Karl... 你想达到什么目的?除了将 JS 内联到您的 HTML 相当不优雅(而且通常效率低下,因为它围绕代码创建一个包装函数)这一事实之外,您 总是 返回 false 的事实意味着您的表单将 从不提交。因此,除非该表单不打算提交(也许它完全由 JS 代码使用),或者除非 myFunc(this) 通过 AJAX 提交它(并且您不关心在 AJAX 的情况下执行常规提交作为后备以某种方式失败),......那么你犯了一个错误。 通常,要仅提交有效的表单数据,您会这样做:myform.onsubmit = validateForm;(其中 myform 是引用表单元素的变量,而 validateForm 是您的验证函数的名称......但是您如果你真的真的想要,可以将它命名为myFunc)。重要的一点是validateForm() 应该在表单无效时返回 false,并向用户指示问题字段。当表单数据正确验证时,它应该返回 true,这将允许提交操作继续进行。 在表单字段中避免使用 id 的另一个原因是:如果您想要同一表单的多个实例(在同一页面中)。 @João 也可以,provided "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。 关于 linting,请记住 linting 只是一种样式指南,linting“错误”并不意味着您的 javascript 无效或不正确。但是,在这种特殊情况下,linting 规则所说的是“在引用 javascript 对象属性时首选点表示法”。这是个好主意,我一般建议这样做。 但是虽然 linter 没有意识到这一点,elements 不是普通的 JS 对象,elements.fooelements["foo"] 实际上正在转换为 elements.namedItem("foo")。即你正在调用一个 DOM 定义的 函数,而不是引用一个 JS 属性!【参考方案2】:

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

No-omg-never!”当我看到这种元素访问方法时,我就想到了。这样做的问题是它假设 DOM 是一个正常的数据结构(例如:一个数组),其中元素顺序无论如何都是静态的、一致的或可靠的。我们知道 99.9999% 的情况并非如此。在表单中重新排序或input 元素,在相关表单之前的页面中添加另一个form,或移动相关表单都是此代码中断的情况。短篇小说:这是非常脆弱的。只要您添加或移动某些东西,它就会损坏。

[2] 文档.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更可取。


我碰巧在看video from Douglas Crockford,他就这个话题发表了看法。兴趣点位于 -12:00。总结一下:

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

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

【讨论】:

所以这只是一个 hack 吗? document.getElementById("myform").foo;在对 DOM 进行了相当多的研究之后,我不清楚这为什么会起作用。我的猜测是表单对象也是在 html name 属性上索引的子元素的数组... 您还提到“名称不会作为 POST/GET 的一部分传递给服务器,并且不适用于哈希样式书签”。这不正是传递给服务器的内容吗?当您使用 php 时,name 属性是您在 $_POST 全局中的索引。 @Justin,这是传递给服务器的名称属性。 @seth 较早的 DOM 规范似乎对 document.aForm.foo 起作用的原因非常模糊,但 HTML5 规范似乎清楚地定义了具有 caller getter any namedItem(in DOMString name);HTMLFormElement 的接口。更多whatwg.org/specs/web-apps/current-work/multipage/… @both 你们:“...... name 属性在应用于表单时是无用的......”我不是在谈论 inputselect 的 name 属性,我说的是form 的名称属性。 form 的名称属性不会传递给服务器。【参考方案3】:

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

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

【讨论】:

“使用表单对象本身”是什么意思?获得表单对象后,您使用什么方法来访问特定元素? 我的意思是我建议使用 N5 (document.getElementById('myForm').elements.foo) 来访问命名项目和 N6 (document.getElementById('myForm').elements) 来访问可迭代的元素集合 我正在定义我的代码风格...作为偏好,我坚持使用 ID ....这样元素访问在整个页面中是一致的。 + 提到的其他原因。 为什么使用 getElementID 访问表单是一个好习惯?为什么 document.myForm 不起作用? (我有一种情况,它不工作,我想知道为什么) Hey Spundun,您可能几个月前就解决了您的问题(或者您可能举手了 :)),但如果您想知道,这可能是由于您没有为表单 HTML 元素提供“名称”属性。【参考方案4】:

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

[3] 需要一个 id 和一个名字...同时拥有这两者有点多余

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

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

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

这有点多余,尽管当您有复选框/单选按钮时,它们中的几个可以共享name。最终,idname 用于不同的目的,即使两者通常设置为相同的值。

【讨论】:

如果将输入包装在其标签中,则不需要 id 或 for 属性。 非常正确,尽管这确实限制了您在外观和感觉方面所能达到的效果。 @kennebec — 如果您希望标签与元素相关联,则应始终使用 id。如果没有匹配的 forid 属性,旧版本的 IE ( 除了@kennebec 写的,使用 ID 会创建 JS 全局变量,应该避免。 @mikemaccana:我以前见过导致问题的原因。我确实认为,如果您的 ID 具有合理的描述性并且您的 JavaScript 命名空间合理,那么它不太可能导致问题。【参考方案5】:

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

具体来说,对于表单:

<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,尽管它确实需要知道权重限制字段的名称。

【讨论】:

不确定根本原因是什么,但我已经让这种方法在某些(但不是全部)情况下返回空字符串。【参考方案6】:

这有点旧,但我想添加一个我认为相关的内容。 (我的意思是评论上面的一两个线程,但似乎我需要声望 50,而我在写这篇文章时只有 21。:)) 只想说,有时通过名称而不是 id 访问表单的元素要好得多。我不是在谈论表格本身。表单,OK,你可以给它一个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>

您可以通过使用整体获取/设置单选按钮R1的选中值 document.mainForm.R1.value 或 document.getElementById("mainForm").R1.value 因此,如果您想要一个单一的样式,您可能希望始终使用此方法,而不管表单元素的类型如何。我,我非常喜欢按名称访问单选按钮和按 ID 访问文本框。

【讨论】:

有效的是document.forms.mainForm.R1.value,这确实是避免使用丑陋和乏味的document.getElementById()的好方法【参考方案7】:

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

【讨论】:

你可以插入.forms,所以document.forms.myform.myvar【参考方案8】:

只是为了补充已经说过的所有内容,您可以使用 nameid 访问 inputs,最好使用 Object 表单的 elements 属性,因为没有它,您可能会获得以下属性名为“foo”的表单而不是 HTML 元素。根据@Paul D. Waite 的说法,同时拥有 name 和 id 是完全可以的。

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 列出了包含在 元素。独立地,您可以仅获得 使用长度属性的表单控件。

您可以通过以下方式访问返回集合中的特定表单控件 使用索引或元素的 nameid

【讨论】:

【参考方案9】:

name 属性效果很好。它提供了对elements 的引用。

parent.children - 将列出所有具有父名称字段的元素。 parent.elements - 将仅列出 form elements,例如 input-texttext-area 等。

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 必须是&lt;form&gt; 标记。而.children 将适用于任何 HTML 元素 - 例如 &lt;div&gt;&lt;span&gt; 等。

【讨论】:

字段?不是属性吗?【参考方案10】:

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

【讨论】:

按名称、id 和索引访问表单和表单控件是HTML collections 的 DOM 2 HTML 标准的一部分。【参考方案11】:

表格2还可以,表格3也推荐。

nameid 之间的冗余是因为需要保持兼容性。在 HTML5 中,一些元素(例如 imgformiframe 等)会失去它们的“name”属性,建议只使用他们的 id 从现在开始引用他们 :)

【讨论】:

由于服务器端语言的使用方式,输入元素似乎永远不会丢失其名称属性。那么问题来了,如果只设置了 name 属性,符合标准的方法是什么? 在符合标准的开发中,对于初学者来说,您不会只有名称。如果你真的不能有 ID,那么我建议使用 document.getElementByName() 函数。【参考方案12】:

查看此页面:Document.getElementsByName()

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

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

【讨论】:

@robert,我现在认为这可能是一个很好的解决方案,尽管这直接来自文档让我感到紧张:“鉴于文档类型和XHTML 中此方法的当前非标准行为。" 您好。哪些文件建议反对这一点?我认为如果您在所有工作的 DOM 环境中都使用 xhtml,那么您应该没问题。另外,哪些浏览器不支持这个?这是 IE 的文档:msdn.microsoft.com/en-us/library/ms536438(VS.85).aspx 除了上面的 Mozilla,还有谁可能不支持它?【参考方案13】:

我的回答会在具体问题上有所不同。 如果我想专门访问某个元素,那么我将使用 document.getElementById()。 一个例子是计算一个人的全名,因为它建立在多个字段之上,但它是一个可重复的公式。

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

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

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

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

【讨论】:

【参考方案14】:

我更喜欢这个

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

【讨论】:

欢迎来到 SO,我们感谢您的意见。请编辑您的答案并解释原因和方式。 你可以edit (changing) your answer(但没有“编辑:”、“更新:”或类似的 - 答案应该看起来好像今天写的)。【参考方案15】:

因为 case [2] document.myForm.foo 是 Internet Explorer 的方言。

所以我更喜欢document.forms.myForm.elements.foodocument.forms["myForm"].elements["foo"],而不是它。

【讨论】:

【参考方案16】:

老问题,新见解(2021 年)

在阅读并学习了这个问题的一些优秀答案后,需要回到基础并尝试获取更多数据idname是如何定义的在他们的起源

结果简单而富有启发性。我总结如下:


最重要的事实是,到目前为止idname 如此不同,用途也如此不同,因此它们在不同的部分中定义 的 W3/WHATWG 规范。简而言之: id: 定义为 DOM(Web 文档标准)规范的一部分,而不是 HTML(标记语言)。 所以,id 是 DOM(文档),而不是 HTML(语言)。 其目的直接与文档中节点的唯一标识相关。因此,非常适合访问节点必须是唯一的 name: 定义为 HTML 规范的一部分,而不是 DOM。 因此,name 是 HTML(语言),而不是 DOM(网络文档)。 其用途直接表单提交相关 - 表单的结构、其编码类型、发送到服务器的数据(例如通过 https)等等开。
根据以上数据和作为开发者积累的一些经验,我的主要结论是
    混淆关于使用idname 访问元素 是由一些主要因素造成的: 虽然元素这个术语在 DOM 规范中有明确的定义,但在 HTML 规范中并没有非常明确的定义——它指的是 DOM、xhtml 命名空间等。 我们,开发人员,不喜欢深入研究定义的技术细节(也许我不需要在这里详细说明这个假设),这可能会导致进一步的误解。 因此,术语 元素 被广泛用于指代 HTML 标记(例如,form)和 DOM 节点(尽管 form 是DOM 中的节点,但反之亦然。) JavaScript 提供了多种访问 DOM 中的 事物 的方法,包括基于它自己的东西的方法,例如 (getElementsByTagName、getElementsByName) 这需要一些幕后操作来从 DOM 中检索实际的节点 一方面,它使开发人员更容易访问这些元素;另一方面,它隐藏了在特定上下文中发挥重要作用的概念和结构。 最终,上述因素会产生混淆,从而引发必要且巧妙的问题,例如引发整个线程的问题。 在阅读了答案和 cmets,收集了数据,通过分析数据并得出结论,烧毁了一些神经元后,我对问题的回答是: 如果您想保持严格的技术性(并且可能在性能方面有所提升),那么请尽可能使用id 并且有意义 - 例如,在任何地方添加id 是没有意义的;在radio 输入类型中使用id 属性可能没有意义。 如果您想使用 JavaScript 提供的灵活性,但又想兼顾两全其美,我建议您使用 solution provided by @Doin in this thread。 我也很欣赏@paul-d-waite 带来的可访问性因素。 this 回答中也探讨了相同的因素。 请记住,并非尽你所能

参考资料:

    HTML - name HTML - element DOM - id DOM - element HTML - Living Standard — Last Updated 5 November 2021 DOM - Living Standard — Last Updated 18 October 2021

The form element也值得一看


*** 中的其他参考资料:

was the name attribute really needed in html?

Difference between id and name attributes in HTML


奖金:Short and cool distinction between id and name, for the impatient.

【讨论】:

以上是关于最佳实践:通过 HTML id 或 name 属性访问表单元素?的主要内容,如果未能解决你的问题,请参考以下文章

属性和实例变量的最佳实践

csharp 演示使用select属性仅检索相关项的name属性的Aras最佳实践。

JAXB最佳实践

csharp 演示使用idlist属性根据id数组检索项目的Aras最佳实践。

PythonDjango 时间字段 最佳实践

基于 Facebook Id 检索 Firebase uid 的最佳实践