簡體   English   中英

最佳實踐:通過 HTML id 或 name 屬性訪問表單元素?

[英]Best Practice: Access form elements by HTML id or name attribute?

任何經驗豐富的 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)特別感興趣。

只給你的表單一個id ,你只輸入一個名稱

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

那么訪問輸入元素的最符合標准且問題最少的方法是通過:

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

使用.elements["foo"]而不是.foo更可取,因為后者可能返回名為 "foo" 的表單屬性而不是 HTML 元素!

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

No-omg-never! ”當我看到這種元素訪問方法時,我想到了。 問題在於它假設 DOM 是一個普通的數據結構(例如:數組),其中元素順序無論如何都是靜態的、一致的或可靠的。 我們知道 99.9999% 的情況並非如此。 在表單中重新排序或input元素、在有問題的表單之前向頁面添加另一個form或移動有問題的表單都是此代碼中斷的所有情況。 小故事:這是非常脆弱的。 一旦您添加或移動某些東西,它就會損壞。

[2] document.myForm.foo;

我和謝爾蓋·伊林斯基在一起

  • 通過引用它們的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)曾經是可以互換的,但它們不再是了。”

所以你有它。 從語義上講,這是最有意義的。

要訪問放置在表單中的命名元素,最好使用form對象本身。

要訪問 DOM 樹中有時可能在表單中找到的任意元素,請使用getElementById和元素的id

我更喜歡第 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,盡管它確實需要知道權重限制字段的名稱。

它並沒有真正回答你的問題,而只是在這一部分:

[3] 需要一個 id 和一個名字......同時擁有兩者有點多余

無論如何,您很可能需要在每個表單字段上都有一個id屬性,以便您可以將其<label>元素與其關聯,如下所示:

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

這是可訪問性所必需的(即,如果您不關聯表單標簽和控件,您為什么如此討厭盲人?)。

它有點多余,盡管當您有復選框/單選按鈕時,它們中的幾個可以共享一個name 最終, idname用於不同的目的,即使兩者通常設置為相同的值。

這有點舊,但我想添加一個我認為相關的內容。
(我打算對上面的一兩個線程發表評論,但似乎我需要 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>

您可以使用
document.mainForm.R1.value
或者
document.getElementById("mainForm").R1.value
所以如果你想要一個單一的樣式,你可能想要總是使用這個方法,不管表單元素的類型。 我,我非常喜歡按名稱訪問單選按鈕和按 id 訪問文本框。

老式的我一直使用“document.myform.myvar”語法,但我最近發現它在 Chrome 中失敗了(在 Firefox 和 IE 中可以)。 這是一個Ajax 頁面(即加載到div 的innerHTML 屬性中)。 也許 Chrome 沒有將表單識別為主文檔的一個元素。 我改用了 getElementById (不引用表單),它工作正常。

只是為了添加到已經說過的所有內容,您可以使用nameid訪問input s,最好使用 Object 表單的elements屬性,因為沒有它,您可能會獲得名為“foo”的表單屬性而不是 HTML 元素. 根據@Paul D. Waite 的說法,擁有姓名和 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,列出元素中包含的所有表單控件。 獨立地,您可以使用 length 屬性僅獲取表單控件的數量。

您可以使用索引或元素的名稱id訪問返回集合中的特定表單控件。

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 .elements必須是<form> tag .children將適用於任何HTML-element - 例如<div>, <span>, etc

祝你好運...

我的答案會在確切的問題上有所不同。 如果我想專門訪問某個元素,那么我會使用 document.getElementById()。 一個例子是計算一個人的全名,因為它建立在多個字段上,但它是一個可重復的公式。

如果我想將元素作為功能結構(表單)的一部分來訪問,那么我將使用:

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

從業務的角度來看,這也是它的工作方式。 循環內的變化伴隨着應用程序的功能變化而發生,因此是有意義的。 我將它主要用於用戶友好的驗證和防止網絡調用檢查錯誤數據。 我重復驗證服務器端(並添加更多內容),但如果我可以幫助用戶客戶端,那么對所有人都有好處。

對於數據聚合(例如基於表單中的數據構建餅圖),我使用配置文檔和定制的 Javascript 對象。 然后是該字段與其上下文相關的確切含義,我是否使用 document.getElementById()。

表格2可以,表格3也推薦。
name和id之間的冗余是為了保持兼容性造成的,在html 5上一些元素(如img、form、iframe等)將失去它們的“name”屬性,建議從現在開始只使用它們的id來引用它們在 :)

查看此頁面:https ://developer.mozilla.org/En/DOM/Document.getElementsByName

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

它必須是“元素”並且必須返回一個數組,因為多個元素可以具有相同的名稱。

我更喜歡這個

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

因為案例 [2] document.myForm.foo是 Internet Exploere 的方言。 因此,我更喜歡document.forms.myForm.elements.foodocument.forms["myForm"].elements["foo"] ,而不是它。

舊問題,新見解(2021)

在閱讀並學習了這個問題的一些優秀答案之后,需要回到基礎知識並嘗試獲取更多數據,了解如何在其起源定義idname

結果同時令人震驚,簡單而有啟發性(它讓我大吃一驚!)。

我總結如下:


  • 到目前為止最重要的事實是idname是如此不同並且具有如此不同的用途,因此它們在 W3/WHATWG 規范的不同部分中進行了定義 簡而言之:
    • id
      • 定義為 DOM(網絡文檔標准)規范的一部分,而不是 HTML(標記語言)。 因此, id是 DOM(文檔),而不是 HTML(語言)
      • 其目的與文檔中節點的唯一標識直接相關。 因此,非常適合接入節點
      • 必須是唯一的
    • name :
      • 定義為 HTML 規范的一部分,而不是 DOM。 因此, name是 HTML(語言),而不是 DOM(網絡文檔)。
      • 它的目的與表單提交直接相關——表單的結構、編碼類型、發送到服務器的數據(例如,通過 https)等等。

  • 基於以上數據和作為開發者積累的一些經驗,我的主要結論是
    1. 關於使用idname訪問元素的混淆是由一些主要因素引起的
      • 雖然 DOM 規范中明確定義了術語元素,但它在 HTML 規范中並沒有非常明確的定義——指的是 DOM、xhtml 命名空間等。
      • 我們,開發人員,不喜歡深入研究定義的技術細節(也許我不需要在這里詳細說明這個假設),這可能會導致進一步的誤解。
      • 因此,術語元素被廣泛用於指代 HTML 標簽(例如, form )和 DOM 節點(盡管form是 DOM 中的節點,但反之亦然。)
      • JavaScript 提供了多種訪問 DOM 中事物的方法,包括基於其自身內容的方法,例如 (getElementsBy TagName , getElements ByName ),這需要一些幕后操作才能從 DOM 中檢索實際節點
      • 一方面,它使開發人員更容易訪問這些元素 另一方面,它隱藏了在特定上下文中發揮重要作用的概念和結構。
      • 最終,上述因素會產生混淆,從而導致必要且巧妙的問題,例如引發整個線程的問題。
    2. 在閱讀了答案和評論,收集數據,通過分析數據並得出結論來燒掉一些神經元后,我對這個問題的回答是
      • 如果您想保持嚴格的技術性(並且可能在性能上有所提高),那么請盡可能使用id並且有意義 - 例如,在任何地方添加id都是沒有意義的; radio輸入類型中使用id屬性可能沒有意義。
      • 如果您想使用 JavaScript 提供的靈活性,但同時保持兩全其美,我建議使用@Doin 在此線程中提供解決方案
      • 我也很欣賞@paul-d-waite帶來的可訪問性因素。 答案中也探討了相同的因素。
      • 請記住,並非您所能做的一切都是您應該做的。

參考:

  1. HTML - name
  2. HTML - element
  3. DOM - id
  4. DOM - element
  5. HTML - 生活標准 - 最后更新於 2021 年 11 月 5 日
  6. DOM - 生活標准 - 最后更新於 2021 年 10 月 18 日

也值得看看form元素


Stackoverflow 中的其他參考資料:

html 中真的需要 name 屬性嗎?

HTML 中 id 和 name 屬性的區別


獎勵: idname之間簡短而酷的區別,對於不耐煩的人。

為了補充其他答案,document.myForm.foo 是所謂的 DOM 級別 0,這是 Netscape 實現的方式,因此即使大多數瀏覽器都支持它,它也不是真正的開放標准。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM