知识点:
表单是前后端数据交互的一种重要方式,使用js操作表单也是十分常见的。不过好像每次到表单操作我都要去查API,所以本次想对表单的常用操作做个小结,以备后面随时查看。
首先,我们要知道如下的一些知识:
1. 表单字段在向后台提交数据时,使用的是表单控件的name属性的value,与id无关。(大家可以在百度搜细说表单找到Fish Li大神的这篇文章看看)
2. 表单向服务端传数据时会经过编码。目前基本上只会只使用二种编码规则:application/x-www-form-urlencoded 和 multipart/form-data , 这二个规则的使用场景简单地说就是:后者在上传文件时使用,其它情形则使用前者(默认)。当使用ajax的post方式向后端传数据时,也会常常设置其header头来模拟表单的数据提交方式:xhr.setRequestHeader(‘cotent-type’, ‘application/x-www-form-urlencoded ’);这样后端程序就可以像处理表单数据那种处理传过来的参数了
3. 表单字段共有的属性包括:
① disbled: 布尔值,表示当前字段是否禁用
② readOnly: 布尔值,表示当前字段是否是只读的
③ type: 当前字段类型,对input元素来说,type属性就等于其html中写定的type属性,如text, password, checkbox, radio, submit, textarea..
但要注意select元素的type,对于单选的select元素,其type为select-one, 多远的select元素,type为select-multiple
④ name:当前字段的名称,也是作为有效控件默认向服务器传送数据时的key
⑤ value: 对多远的select元素的value,select.value只能取到第一个选中option的value; 要获取checkbox和radio的value只有通过遍历。除此之外,其它元素的value即是将发向服务器的value,可以通过element.value直接得到
⑥ tabIndex: 当前字段的tab切换序号
⑦ form: 字段所属的表单
除了form属性不能写之外,其它共有属性都是可读写的
4 . 表单字段共的有方法有:focus(), blur()
5. 表单字段共有的事件有:focus, blur, change
6. select元素的额外方法:
除了表单字段共有的属性和方法外,select元素还有下列属性和方法:
① add(newOption, relOption), 向select元素中插入新的option, 新插入的option的位置在relOption之前
② opitions: 得到所有的option的HTMLCollection
③ remove(index): 移除指定位置的option
④ selectIndex: 获取选中项的索引(从0开始),若没有选中项,返回-1,对于支持多选项的select,返回第一个选中的项
⑤ size: 选择框中可见的行数,等价于HTML中的size属性
⑥ select的type属性为select-one/select-multiple
⑦ 如果没有选中项,select的value为空字符串 (“”);如果有一个选中项,且其option的value已经指定,则select的value为选中的option的value, 即使选中的option的value的值为空串;若选中的option的value值没有指定,则select的value为此option的文本;若有多个选中项,select的value以第一个选中的项为准
对于option元素,为了方便访问数据,HTMLOptionElement包含了以下属性:
① index: 此选项在options集合中的索引
② label:此选项的标签,等价于HTML中的label特性
③ selected:此选项是否被选中
④ text: 此选项的文本
⑤ value:此选项的值,等价于HTML中的value
实际练习
select操作封装:
select: { //select操作 addItem: function(select, value, text, pos) { var option = document.createElement('option'); option.setAttribute('value', value); option.innerHTML = text; if(pos) { select.insertBefore(option, select.querySelectorAll('option')[pos]); } //注意这里传了一个undefined参数, select.add(option, undefined); return option; }, removeItem: function(select, index) { //可以使用select.options访问所有的options元素 select.removeChild(select.options[index]); //select.remove(index) 这样也可以 }, selectItemByIndex: function(select, index) { var options = select.options; options[index].selected = true; }, selectItemByVal: function(select, val) { var options = select.options, index; for(var i = 0, l = options.length; i < l; i++) { if(options[i].value === val) { index = i; break; } } this.selectItemByIndex(select, index); }, val: function(select, value) { if(value) { this.selectItemByVal(select, value); } else { return select.value; } }, getSelectedIndex: function(select) { //获取当前选中项的索引, 如果对象有设置mutiple属性,则返回一个索引数组 var ret = [], i = 0, options, temp; if(! select.multiple) { return select.selectedIndex; } options = select.options; while(temp = options[i]) { if(temp.selected) ret.push(i) i++; } return ret; } }
checkbox封装:
checkbox: { all: function(checkboxs, flag) { //全选, 全不选, flag === true,全选中, flag === false,全不选 var checkbox, i = 0; while(checkbox = checkboxs[i]) { checkbox.checked = flag; i++; } }, inverse: function(checkboxs) { //反选 var checkbox, i = 0; while(checkbox = checkboxs[i]) { checkbox.checked = !checkbox.checked; i++; } }, selectItemByVal: function(checkboxs, val) { var index; for(var i = 0, l = checkboxs.length; i < l; i++) { if(checkboxs[i].value === val) { checkboxs[i].checked = true; break; } } } }
radio封装
radio: { selectItemByIndex: function(radios, index) { if(radios[index]) { radios[index].checked = true; } }, selectItemByVal: function(radios, val) { var index; for(var i = 0, l = radios.length; i < l; i++) { if(radios[i].value === val) { radios[i].checked = true; break; } } } }
取得有效表单控件的name和value,组成一个dataMap
dataMap: function(form) { //取得把有效的表单控件的name和值,组成一个数据map var nameMap = {}, dataMap = {}, name, _slice = [].slice; //查找表单中有效的表单控件: /** * 什么是有效表单控件(参考Fish Li博客-细说表单): 1. 控件不能是【禁用】状态,即指定【disabled="disabled"】。即:禁用的控件将不是成功控件。 2. 如果一个表单包含了多个提交按键,那么仅当用户点击的那个提交按钮才算是成功控件。 3. 对于checkbox控件来说,只有被用户勾选的才算是成功控件。 4. 对于radio button来说,只有被用户勾选的才算是成功控件。 5. 对于select控件来说,所有被选择的选项都做为成功控件,name由select控件提供。 6. 对于file上传文件控件来说,如果它包含了选择的文件,那么它将是一个成功控件。 */ //收集input元素的name _slice.call(form.querySelectorAll('input')).forEach(function(e, i) { var name = e.name; if(! nameMap[name]) nameMap[name] = name; }); //收集select元素的name _slice.call(form.querySelectorAll('select')).forEach(function(e, i) { var name = e.name; if(! nameMap[name]) nameMap[name] = name; }); //收集textarea _slice.call(form.querySelectorAll('textarea')).forEach(function(e, i) { var name = e.name; if(! nameMap[name]) nameMap[name] = name; }); //遍历nameMap,并取得相应的表单控件的值,组成dataMap for(name in nameMap) { if(nameMap.hasOwnProperty(name)) { _slice.call(document.getElementsByName(name)).forEach(function(e, i) { if(e.type === 'checkbox'|| e.type === 'radio') { //可能多远 dataMap[name] = dataMap[name] || []; if(e.checked) { dataMap[name].push(e.value); } } else if(e.type === 'select-multiple') { //注意可以多选的select的type属性为 select-multiple //可能多选 dataMap[name] = dataMap[name] || []; _slice.call(e.options).forEach(function(e, i) { if(e.selected) { dataMap[name].push(e.value); } }); } else { dataMap[name] = e.value; } }) } } return dataMap; }
练习时的源代码:下载地址