最佳实践:通过 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
属性的值几乎没有限制,因此例如您可以使用<select name="a+b">
或<input type="text" name="...2">
,不能使用javascript .propertyName 表示法引用)。显式 [] 表示法还允许从表达式构建名称,例如myCheckBox = document.getElementById("myform").elements["CHK"+i]
。另外,在风格上,我认为 [] 更好——它清楚地表明这些不仅仅是 javascript 对象的属性。 YMMV。
关于 linting,请记住 linting 只是一种样式指南,linting“错误”并不意味着您的 javascript 无效或不正确。但是,在这种特殊情况下,linting 规则所说的是“在引用 javascript 对象属性时首选点表示法”。这是个好主意,我一般建议这样做。 但是虽然 linter 没有意识到这一点,elements
不是普通的 JS 对象,elements.foo
或 elements["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 属性在应用于表单时是无用的......”我不是在谈论 input
或 select
的 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
属性,以便您可以将其<label>
元素与其关联,如下所示:
<label for="foo">Foo:</label>
<input type="text" name="foo" id="foo" />
这是可访问性所必需的(即,如果您不关联表单标签和控件,为什么您会如此讨厌盲人?)。
这有点多余,尽管当您有复选框/单选按钮时,它们中的几个可以共享name
。最终,id
和 name
用于不同的目的,即使两者通常设置为相同的值。
【讨论】:
如果将输入包装在其标签中,则不需要 id 或 for 属性。 非常正确,尽管这确实限制了您在外观和感觉方面所能达到的效果。 @kennebec — 如果您希望标签与元素相关联,则应始终使用 id。如果没有匹配的 for 和 id 属性,旧版本的 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】:
只是为了补充已经说过的所有内容,您可以使用 name
或 id
访问 input
s,最好使用 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 列出了包含在 元素。独立地,您可以仅获得 使用长度属性的表单控件。
您可以通过以下方式访问返回集合中的特定表单控件 使用索引或元素的 name 或 id。
【讨论】:
【参考方案9】:name
属性效果很好。它提供了对elements
的引用。
parent.children
- 将列出所有具有父名称字段的元素。
parent.elements
- 将仅列出 form elements
,例如 input-text
、text-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
必须是<form>
标记。而.children
将适用于任何 HTML 元素 - 例如 <div>
、<span>
等。
【讨论】:
字段?不是属性吗?【参考方案10】:为了补充其他答案,document.myForm.foo 是所谓的 DOM 级别 0,这是 Netscape 实现的方式,因此即使大多数浏览器都支持它,它也不是真正的开放标准。
【讨论】:
按名称、id 和索引访问表单和表单控件是HTML collections 的 DOM 2 HTML 标准的一部分。【参考方案11】:表格2还可以,表格3也推荐。
name 和 id 之间的冗余是因为需要保持兼容性。在 HTML5 中,一些元素(例如 img、form、iframe 等)会失去它们的“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.foo
或document.forms["myForm"].elements["foo"]
,而不是它。
【讨论】:
【参考方案16】:老问题,新见解(2021 年)
在阅读并学习了这个问题的一些优秀答案后,需要回到基础并尝试获取更多数据id
和name
是如何定义的在他们的起源。
结果简单而富有启发性。我总结如下:
最重要的事实是,到目前为止,
id
和 name
如此不同,用途也如此不同,因此它们在不同的部分中定义 的 W3/WHATWG 规范。简而言之:
id
:
定义为 DOM(Web 文档标准)规范的一部分,而不是 HTML(标记语言)。 所以,id
是 DOM(文档),而不是 HTML(语言)。
其目的直接与文档中节点的唯一标识相关。因此,非常适合访问节点。
必须是唯一的
name
:
定义为 HTML 规范的一部分,而不是 DOM。 因此,name
是 HTML(语言),而不是 DOM(网络文档)。
其用途直接与表单提交相关 - 表单的结构、其编码类型、发送到服务器的数据(例如通过 https)等等开。
根据以上数据和作为开发者积累的一些经验,我的主要结论是:
-
混淆关于使用
id
或name
访问元素 是由一些主要因素造成的:
虽然元素这个术语在 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最佳实践。