Найкраща практика: Доступ до елементів форми за HTML-атрибутом чи атрибутом імені?


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 або атрибут імені (наявність обох дещо зайва, особливо якщо ідентифікатор не потрібен жодному css та збільшує ймовірність помилок друку тощо).

[2], здається, найбільш інтуїтивно зрозуміло, і воно, здається, широко використовується, але я не бачив, щоб на нього згадувалося в документації про Gecko, і я переживаю як про сумісність вперед, так і про сумісність браузера (і, звичайно, хочу бути якомога більше відповідають стандартам).

То яка найкраща практика тут? Чи може хтось вказати на щось у документації DOM або специфікації W3C, що могло б це вирішити?

Примітка Мене спеціально цікавить небібліотечне рішення (jQuery / Prototype).


Я здогадуюсь, що це зводиться до того, що я шукаю найбільш сумісний із стандартами спосіб доступу до елемента форми за допомогою атрибута імені ...
seth

4
"наявність обох дещо зайва, особливо якщо ідентифікатор не потрібен жодному css і збільшує ймовірність помилок друку" - ID необхідний для ефективного використання міток. Не лише CSS.

Іноді на веб-сторінці є кілька форм, і атрибути id можуть стикатися.
Кальмарій

Відповіді:


96

Укажіть форму лише ідентифікатор , а ваше введення лише ім’я :

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

Тоді найздатніший стандарт та найменш проблемний спосіб отримати доступ до вхідного елемента через:

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

використання .elements["foo"]замість просто .fooє кращим, оскільки останнє може повернути властивість форми під назвою "foo", а не HTML-елемент!


1
@Karl ... Чого ти намагаєшся досягти? Крім того, що вбудований JS у ваш HTML є досить неелегантним (і часто неефективним, оскільки він створює функцію обгортки навколо коду), той факт, що ви завжди повертаєте помилкове, означає, що ваша форма ніколи не надсилатиметься. Тому, якщо або форма не призначена для надсилання (можливо, вона використовується повністю за допомогою JS-коду), або якщо myFunc (це) подає її через AJAX (і вам не байдуже робити регулярне надсилання як резервний випадок у випадку AJAX провалюється якось), ... то ви помилилися.
Doin

1
Зазвичай, щоб представити тільки дійсний вид даних, ви могли б зробити: myform.onsubmit = validateForm;(де MyForm є змінною , що посилається на елемент форми, і validateForm це ім'я вашої функції перевірки ... але ви можете назвати його MyFunc , якщо ви дійсно , дійсно хочете ). Важливим моментом є те, що validateForm()слід повертати помилкові, коли форма недійсна, а також вказати користувачеві проблемні поля. Він повинен повернути істину, коли дані форми перевіряються правильно, що дозволить дії надсилати вперед.
Робити

2
Є ще одна причина уникати ідентифікаторів у полях форм: якщо вам потрібно кілька примірників однієї форми (на одній сторінці).
коріандр

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». Це гарна ідея, і я рекомендую це взагалі. АЛЕ в той час як Лінтера не розуміє цього, elementsне є нормальним об'єктом JS, і elements.fooчи elements["foo"]фактично отримувати перетворюється в elements.namedItem ( «Foo»). тобто ви викликаєте визначену DOM функцію , не посилаючись на властивість JS!
Doin

34

[1] document.forms [0] .елементи [0];

" Ні-що-ніколи! " Приходить до тями, коли я бачу цей метод доступу до елементів. Проблема в цьому полягає в тому, що він передбачає, що 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 є кращим.


Мені просто так трапилось подивитися відео з Дугласа Крокфорда, і він зважився на цю саму тему. Цікавий об’єкт - -12: 00. Узагальнити:

  • Колекції документів (document.anchor, document.form тощо) є застарілими та неактуальними (метод 1).
  • nameАтрибут використовується , щоб назвати речі, а чи не до них доступ. Він призначений для іменування таких речей, як Windows, поля введення та теги прив’язки.
  • "Ідентифікатор - це те, що вам слід використовувати, щоб однозначно ідентифікувати елемент, щоб ви могли отримати доступ до нього. Вони (ім'я та ідентифікатор) раніше були взаємозамінними, але вони більше не є."

Так ось у вас це є. Семантично це має найбільше значення.


2
Так це просто хакер? document.getElementById ("myform"). foo; Вивчивши DOM зовсім небагато, мені незрозуміло, чому це взагалі працює. Я здогадуюсь, що об’єкт форми також є масивом його дочірніх елементів, індексованих атрибутом html ім'я ...
вересень

1
Також ви згадуєте, що "ім'я не передається серверу як частина POST / GET і не працює для закладок у стилі хеш". Чи не саме це передано на сервер? Під час роботи з PHP атрибут name є вашим індексом у глобальному $ _POST.
seth

2
@Justin, це атрибут імені, який передається серверу.
Анураг

2
@seth Старі специфікації DOM здаються дуже невиразними щодо того, чому document.aForm.fooпрацює, але специфікація HTML5, схоже, чітко визначає інтерфейс, HTMLFormElementякий має caller getter any namedItem(in DOMString name);. Більше на whatwg.org/specs/web-apps/current-work/multipage/…
Анураг

1
@both, хлопці: "... атрибут імені марний при застосуванні до форми ..." Я не говорю про атрибут name inputабо select, я кажу про атрибут name form. Атрибут імені а form не передається серверу.
Джастін Джонсон

14

Для доступу до названих елементів, розміщених у формі, є хорошою практикою використовувати сам formоб’єкт.

Щоб отримати доступ до довільного елемента в дереві DOM, який може бути іноді знайдений у формі, використовуйте getElementByIdта елементи елемента id.


8
Що ви маєте на увазі "використовувати сам об'єкт форми"? Коли у вас є об’єкт форми, який метод ви використовуєте для доступу до певного елемента?
Seth

2
Я маю на увазі, я б рекомендував використовувати N5 (document.getElementById ('myForm'). Elements.foo) для доступу до іменованих елементів та N6 (document.getElementById ('myForm'). Елементів) для доступу до ітерабельної колекції елементів
Сергій Ілінський

Я визначаю стиль свого коду ... і як перевагу я дотримуюся ідентифікаторів .... таким чином доступ до елементів є послідовним на всій сторінці. + інші згадані причини.

1
Чому є доступною формою доступ до форми за допомогою getElementID? Чому document.myForm не працює? (У мене ситуація, коли його не працює, і мені цікаво, чому)
Spundun

Ей, Спундун, ви, ймовірно, вирішили свою проблему місяці тому (або, можливо, ви кинули руки вгору :)), але у випадку, якщо вам було цікаво, це, ймовірно, було через те, що ви не надали HTML-елементу форми атрибут "ім'я".
Шелдон Р.

8

Я дуже віддаю перевагу 5-му методу. Тобто
[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 !=...

Використовуючи цю техніку, функція ніколи не повинна знати
- порядок, у якому форми визначені на сторінці,
- ідентифікатор форми, а також
- назва форми

Аналогічно для полів:

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

У цьому випадку функція ніколи не повинна знати ім'я чи ідентифікатор конкретного вагового поля, хоча це потрібно знати ім'я поля обмеження ваги.


Не впевнений, що є причиною, але я мав такий підхід повертати порожні рядки в деяких, але не у всіх обставинах.
Джейкоб Лі

7

Це не справді відповідає на ваше запитання, а лише в цій частині:

[3] вимагає і ідентифікатора, і імені ... наявність обох є дещо зайвим

Вам, швидше за все, потрібно буде мати idатрибут у кожному полі форми, так що ви можете пов’язати його <label>елемент з ним, як це:

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

Це потрібно для доступності (тобто, якщо ви не пов'язуєте мітки форми та елементи управління, то чому ви так ненавидите сліпих людей?).

Це дещо зайве, хоча менше, якщо у вас є прапорці / радіо кнопки, де декілька з них можуть ділитися name. У кінцевому рахунку, idі nameдля різних цілей, навіть якщо обидва часто встановлюються на одне значення.


5
Якщо ви загортаєте вхід у свою мітку, вам не потрібен ідентифікатор чи атрибут. <label> Foo: <input type = "text" name = "foo" </label>
kennebec

3
Дуже вірно, хоча це обмежує те, чого ви можете досягти в плані зовнішнього вигляду.
Пол Д. Уейт

2
@ kennebec - завжди потрібно використовувати ідентифікатор, якщо ви хочете, щоб мітка асоціювалася з елементом. Більш старі версії IE (<8?) Чи не пов'язував елементи всередині етикетки з етикеткою , якби не було відповідності для і ідентифікатори атрибутів.
RobG

На додаток до того, що написав @kennebec, використання ідентифікаторів створює JS глобалі, яких слід уникати.
mikemaccana

1
@mikemaccana: Я вже бачив, що викликає проблеми. Я думаю, що якщо ваші ідентифікатори мають достатньо описовий характер, а ваш JavaScript чітко простір імен, це навряд чи спричинить проблеми.
Пол Д. Вейт

6

Це трохи старе, але я хочу додати те, що я вважаю актуальним.
(Я мав на увазі коментувати одну або 2 теми вище, але, здається, мені потрібна репутація 50, і у мене є лише 21 час, коли я це пишу. :))
Просто хочу сказати, що бувають випадки, коли набагато краще отримати доступ до елементи форми за назвою, а не за id. Я не кажу про саму форму. Форму, OK, ви можете дати йому ідентифікатор, а потім отримати доступ до нього. Але якщо у вас є перемикач у формі, набагато простіше використовувати його як єдиний об’єкт (отримання та встановлення його значення), і ви можете це робити лише по імені, наскільки я знаю.

Приклад:

<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()
Кай Карвер

2

Будучи старомодним, я завжди використовував синтаксис 'document.myform.myvar', але нещодавно виявив, що це не вдалося в Chrome (OK у Firefox та IE). Це була сторінка Ajax (тобто завантажена у внутрішнюHTML-властивість div). Можливо, Chrome не визнав форму як елемент основного документа. Я замість цього використовував getElementById (без посилання на форму), і він працював нормально.


ви можете просто вставити .forms, так document.forms.myform.myvar
Кай Карвер

1

Для того, щоб додати до всього сказаного, ви можете отримати доступ до inputs або з використанням nameабо, idпереважно, elementsвластивості форми Object, тому що без цього ви можете отримати властивість форми з назвою "foo", а не HTML-елемента. За словами @Paul D. Waite, цілком нормально мати і ім’я, і ідентифікатор.

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>

Згідно MDN на HTMLFormElement.elements сторінці

Елементи властивості HTMLFormElement повертають HTMLFormControlsCollection з переліком усіх елементів форми, що містяться в елементі. Незалежно, ви можете отримати лише кількість елементів форми, використовуючи властивість length.

Ви можете отримати доступ до певного контролю форми у поверненій колекції, використовуючи або індекс, або ім'я або ідентифікатор елемента .


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потреби повинні бути a <form> tag. Тоді як .childrenбуде працювати на будь-якому HTML-element- наприклад, як <div>, <span>, etc.

Щасти...


0

Форма 2 добре, а форма 3 також рекомендується.
Надлишок між ім'ям та ідентифікатором зумовлений необхідністю зберігати сумісність, у html 5 деякі елементи (як img, форма, iframe тощо) втратять атрибут "name", і рекомендується використовувати лише їх id для посилання на них на :)


Здається, елементи введення ніколи не втратять атрибут імені через те, як його використовують серверні мови. Тож залишається питання, який метод відповідає стандартам, якщо у вас є лише встановлений атрибут імені?
Seth

У розробці, сумісному стандартам, у вас не було б лише ім'я для початківців. Якщо ви дійсно НЕ можете мати ідентифікатор, я б запропонував функцію document.getElementByName ().
Wintermute

0

Для доповнення інших відповідей document.myForm.foo - це так званий DOM рівень 0, який є способом, реалізованим Netscape, і, таким чином, насправді не є відкритим стандартом, хоча він підтримується більшістю браузерів.


4
Доступ до форм та елементів керування формою за іменами, ідентифікаторами та індексами є частиною стандарту DOM 2 HTML для колекцій HTML .
RobG

0

Перевірте цю сторінку: https://developer.mozilla.org/En/DOM/Document.getElementsByName

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

Він повинен бути "елементами" і повинен повертати масив, оскільки більш ніж один елемент може мати те саме ім'я.


@robert, я зараз думаю, що це може бути гарним рішенням, хоча це прямо з документів викликає нервозність: "Цей метод може бути сумнівним для використання, враховуючи вищезазначені зміни між типами документів та поточною нестандартною поведінкою для цього" метод в XHTML ".
Seth

Привіт там. Яка документація пропонувала проти цього? Я думаю, якщо ви використовуєте xhtml у всіх середовищах DOM, в яких ви працюєте, тоді вам повинно бути все в порядку. Крім того, які браузери не підтримують це? Ось документи для 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 ().


0

Тому що випадок [2] document.myForm.foo- це діалект від Internet Exploere. Тож замість цього я віддаю перевагу document.forms.myForm.elements.fooабо document.forms["myForm"].elements["foo"].


-1

Я віддаю перевагу цьому

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

2
Ласкаво просимо до SO, ми цінуємо ваш внесок. Відредагуйте свою відповідь та поясніть, чому і як.
B - rian
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.