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

IT技术 javascript html forms dom
2021-01-16 16:24:58

任何经验丰富的 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)特别感兴趣。

6个回答

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

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

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

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

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

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

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

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

[2] document.myForm.foo;

我和谢尔盖 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)曾经是可以互换的,但它们不再是了。”

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

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

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

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

为什么使用 getElementID 访问表单是一个好习惯?为什么 document.myForm 不起作用?(我遇到了无法正常工作的情况,我想知道为什么)
2021-03-12 16:24:58
我的意思是我会建议使用 N5 (document.getElementById('myForm').elements.foo) 来访问命名项目和 N6 (document.getElementById('myForm').elements) 来访问可迭代的元素集合
2021-04-08 16:24:58
我正在定义我的代码的样式......作为一个偏好,我坚持使用 ID......这样元素访问在整个页面上是一致的。+ 提到的其他原因。
2021-04-08 16:24:58
嘿 Spundun,您可能在几个月前解决了您的问题(或者您可能举手了 :)),但如果您想知道,这可能是因为您没有为表单 HTML 元素提供“名称”属性。
2021-04-08 16:24:58
“使用表单对象本身”是什么意思?拥有表单对象后,您使用什么方法来访问特定元素?
2021-04-11 16:24:58

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

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

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

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

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

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

@mikemaccana:我以前见过这会导致问题。我确实认为,如果您的 ID 具有合理的描述性并且您的 JavaScript 命名空间合理,那么它不太可能导致问题。
2021-03-29 16:24:58
非常正确,尽管这确实限制了您在外观和感觉方面可以实现的目标。
2021-04-04 16:24:58
除了@kennebec 写的内容之外,使用 ID 会创建 JS 全局变量,应该避免使用。
2021-04-04 16:24:58
如果将输入包装在其标签中,则不需要 id 或 for 属性。<label>Foo: <input type="text" name="foo" </label>
2021-04-10 16:24:58
@kennebec-如果您希望标签与元素相关联,则应始终使用 id。如果没有匹配的forid属性,旧版本的 IE(< 8?)不会将标签内的元素与标签相关联
2021-04-11 16:24:58

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

不确定根本原因是什么,但我已经让这种方法在某些情况下返回空字符串,但不是所有情况。
2021-03-21 16:24:58