javascript基础从小白到高手系列四千九百七十六:移动和重排选项 在DOM 之前从一个选择框向另一个选择框移动选项是非常麻烦的要先从第一个选择框移除选项然后以相同文本和值创建新选项再将新选项添加到第二个选择框。DOM 方法则可以直接将某个选项从第一个选择框移动到第二个选择框只要对相应选项使用appendChild()方法即可。如果给这个方法传入文档中已有的元素则该元素会先从其父元素中移除然后再插入指定位置。例如下面的代码会从选择框中移除第一项并插入另一个选择框let selectbox1 document.getElementById(“selLocations1”);let selectbox2 document.getElementById(“selLocations2”);selectbox2.appendChild(selectbox1.options[0]);移动选项和移除选项都会导致每个选项的index 属性重置。重排选项非常类似DOM 方法同样是最佳途径。要将选项移动到选择框中的特定位置insertBefore()方法是最合适的。不过要把选项移动到最后还是appendChild()方法比较方便。下面的代码演示了将一个选项在选择框中前移一个位置let optionToMove selectbox.options[1];selectbox.insertBefore(optionToMove,selectbox.options[optionToMove.index-1]);这个例子首先获得要移动选项的索引然后将其插入之前位于它前面的选项之前其中第二行代码适用于除第一个选项之外的所有选项。下面的代码则可以将选项向下移动一个位置let optionToMove selectbox.options[1];selectbox.insertBefore(optionToMove,selectbox.options[optionToMove.index2]);以上代码适用于选择框中的所有选项包括最后一个。表单序列化随着Ajax第21 章会进一步讨论的崭露头角表单序列化form serialization已经成为一个常见需求。表单在JavaScript 中可以使用表单字段的type 属性连同其name 属性和value 属性来进行序列化。在写代码之前我们需要理解浏览器如何确定在提交表单时要把什么发送到服务器。 字段名和值是URL 编码的并以和号分隔。 禁用字段不会发送。 复选框或单选按钮只在被选中时才发送。 类型为reset或button的按钮不会发送。 多选字段的每个选中项都有一个值。 通过点击提交按钮提交表单时会发送该提交按钮否则不会发送提交按钮。类型为image的元素视同提交按钮。 元素的值是被选中元素的value 属性。如果元素没有value 属性则该值是它的文本。表单序列化通常不包含任何按钮因为序列化得到的字符串很可能以其他方式提交。除此之外其他规则都应该遵循。最终完成表单序列化的代码如下function serialize(form) {let parts [];let optValue;for (let field of form.elements) {switch(field.type) {case “select-one”:case “select-multiple”:if (field.name.length) {for (let option of field.options) {if (option.selected) {if (option.hasAttribute){optValue (option.hasAttribute(“value”) ?option.value : option.text);} else {optValue (option.attributes[“value”].specified ?option.value : option.text);}parts.push(encodeURIComponent(field.name)} “” encodeURIComponent(optValue));}}}break;case undefined: // 字段集casefile: // 文件输入case “submit”: // 提交按钮case “reset”: // 重置按钮case “button”: // 自定义按钮break;case “radio”: // 单选按钮case “checkbox”: // 复选框if (!field.checked) {break;}default:// 不包含没有名字的表单字段if (field.name.length) {parts.push(‘encodeURIComponent(field.name)′′{encodeURIComponent(field.name)} encodeURIComponent(field.name)′′{encodeURIComponent(field.value)}’);}}return parts.join(“”);}这个serialize()函数一开始定义了一个名为parts 的数组用于保存要创建字符串的各个部分。接下来通过for 循环迭代每个表单字段将字段保存在field 变量中。获得一个字段的引用后再通过switch 语句检测其type 属性。最麻烦的是序列化元素包括单选和多选两种模式。在遍历选择框的每个选项时只要有选项被选中就将其添加到结果字符串。单选控件只会有一个选项被选中多选控件则可能有零或多个选项被选中。同样的代码适用于两种选择类型因为浏览器会限制可选项的数量。找到选中项时需要确定使用哪个值。如果不存在value 属性则应该以选项文本代替不过value 属性为空字符串是完全有效的。为此需要使用DOM 合规的浏览器支持的hasAttribute()方法而在IE8 及更早版本中要使用值的specified 属性。表单中如果有元素它就会出现在元素集合中但应该没有type 属性。因此如果type 属性是undefined则不必纳入序列化。各种类型的按钮以及文件输入字段也是如此。文件输入字段在提交表单时包含文件的内容但这些字段通常无法转换因而也要排除在序列化之外。对于单选按钮和复选框会检测其checked 属性。如果值为false 就退出switch 语句如果值为true则继续执行default 分支将字段的名和值编码后添加到parts 数组。注意所有没有名字的表单字段都不会包含在序列化结果中以模拟浏览器的表单提交行为。这个函数的最后一步是使用join()通过和号把所有字段的名值对拼接起来。serialize()函数返回的结果是查询字符串格式。如果想要返回其他格式修改起来也很简单。