表单(form)以及例如 的控件(control)元素有许多特殊的属性和事件。
当我们学习了这些相关内容后,处理表单会变得更加方便。

导航:表单和元素

文档中的表单是特殊集合 document.forms 的成员。
这就是所谓的“命名的集合”:既是被命名了的,也是有序的。我们既可以使用名字,也可以使用在文档中的编号来获取表单。

  1. document.forms.my; // name="my" 的表单
  2. document.forms[0]; // 文档中的第一个表单

当我们有了一个表单时,其中的任何元素都可以通过命名的集合 form.elements 来获取到。
例如:

  1. <form name="my">
  2. <input name="one" value="1">
  3. <input name="two" value="2">
  4. </form>
  5. <script>
  6. // 获取表单
  7. let form = document.forms.my; // <form name="my"> 元素
  8. // 获取表单中的元素
  9. let elem = form.elements.one; // <input name="one"> 元素
  10. alert(elem.value); // 1
  11. </script>

可能会有多个名字相同的元素,这种情况经常在处理单选按钮中出现。
在这种情况下,form.elements[name] 将会是一个集合。例如:

  1. <form>
  2. <input type="radio" name="age" value="10">
  3. <input type="radio" name="age" value="20">
  4. </form>
  5. <script>
  6. let form = document.forms[0];
  7. let ageElems = form.elements.age;
  8. alert(ageElems[0]); // [object HTMLInputElement]
  9. </script>

这些导航(navigation)属性并不依赖于标签的结构。所有的控件元素,无论它们在表单中有多深,都可以通过 form.elements 获取到。
Fieldset 作为“子表单”
一个表单内会有一个或多个

元素。它们也具有 elements 属性,该属性列出了
中的表单控件。
例如:

  1. <body>
  2. <form id="form">
  3. <fieldset name="userFields">
  4. <legend>info</legend>
  5. <input name="login" type="text">
  6. </fieldset>
  7. </form>
  8. <script>
  9. alert(form.elements.login); // <input name="login">
  10. let fieldset = form.elements.userFields;
  11. alert(fieldset); // HTMLFieldSetElement
  12. // 我们可以通过名字从表单和 fieldset 中获取 input
  13. alert(fieldset.elements.login == form.elements.login); // true
  14. </script>
  15. </body>

更简短的表示方式:form.name
还有一个更简短的表示方式:我们可以通过 form[index/name] 来访问元素。
换句话说,我们可以将 form.elements.login 写成 form.login。
这也有效,但是会有一个小问题:如果我们访问一个元素,然后修改它的 name,之后它仍然可以被通过旧的 name 访问到(当然也能通过新的 name 访问)。
我们可以很直观地通过一个例子看到这个情况:

  1. <form id="form">
  2. <input name="login">
  3. </form>
  4. <script>
  5. alert(form.elements.login == form.login); // true,与 <input> 相同
  6. form.login.name = "username"; // 修改 input 的 name
  7. // form.elements 更新了 name:
  8. alert(form.elements.login); // undefined
  9. alert(form.elements.username); // input
  10. // form 允许我们使用两个名字:新的名字和旧的名字
  11. alert(form.username == form.login); // true
  12. </script>

这通常来说并不是一个问题,因为我们很少修改表单元素的名字。

反向引用:element.form

对于任何元素,其对应的表单都可以通过 element.form 访问到。因此,表单引用了所有元素,元素也引用了表单。
这是一张示意图:

image.png
例如:

  1. <form id="form">
  2. <input type="text" name="login">
  3. </form>
  4. <script>
  5. // form -> element
  6. let login = form.login;
  7. // element -> form
  8. alert(login.form); // HTMLFormElement
  9. </script>

表单元素

让我们来谈谈表单控件。

input 和 textarea

我们可以通过 input.value(字符串)或 input.checked(布尔值)来访问复选框(checkbox)和单选按钮(radio button)中的 value。
像这样

  1. input.value = "New value";
  2. textarea.value = "New text";
  3. input.checked = true; // 对于复选框(checkbox)或单选按钮(radio button)

使用 textarea.value 而不是 textarea.innerHTML
请注意,即使 将它们的 value 作为嵌套的 HTML 标签来保存,我们也绝不应该使用 textarea.innerHTML 来访问它。
它仅存储最初在页面上的 HTML,而不是存储的当前 value。

select 和 option

一个 设置 value 的不同方式:

  1. 找到对应的
  2. 如果我们知道新的值:将 select.value 设置为对应的新的值。
  3. 如果我们知道新的选项的索引:将 select.selectedIndex 设置为对应

下面是这三种方式的示例:

  1. <select id="select">
  2. <option value="apple">Apple</option>
  3. <option value="pear">Pear</option>
  4. <option value="banana">Banana</option>
  5. </select>
  6. <script>
  7. // 下面这三行做的都是同一件事
  8. select.options[2].selected = true;
  9. select.selectedIndex = 2;
  10. select.value = 'banana';
  11. // 请注意:选项编号是从零开始的,所以编号 2 表示的是第三项
  12. </script>

和大多数其它控件不同,如果 中获取选择的值的示例:

  1. <select id="select" multiple>
  2. <option value="blues" selected>Blues</option>
  3. <option value="rock" selected>Rock</option>
  4. <option value="classic">Classic</option>
  5. </select>
  6. <script>
  7. // 从 multi-select 中获取所有选定的 `value`
  8. let selected = Array.from(select.options)
  9. .filter(option => option.selected)
  10. .map(option => option.value);
  11. alert(selected); // blues,rock
  12. </script>

中的编号。
option.text

参考资料