Ajax深刻精晓ajax体系第6篇——FormData

面前的话

  现代Web应用中再三利用的一项职能正是表单数据的种类化,XMLHttpRequest
2级为此概念了FormData类型。FormData为系列化表单以及开创与表单格式相同的多少提供了便宜。本文将先介绍表单编码,然后对接到表单连串化,最终引出FormData的骨干概念

 

表单编码

  当用户提交表单时,表单中的数据(每一种表单成分的名字和值)编码到1个字符串中并随请求发送。暗许景况下,HTML表单通过POST方法发送给服务器,而编码后的表单数据则用做请求主体

  对表单数据应用的编码方案相对简单:对各种表单成分的名字和值执行日常的U翼虎L编码(使用十六进制转义码替换特殊字符),使用等号把编码后的名字和值分开,并采取”&”符号分开名/值对。2个简练表单的编码如下所示

find=pizza&zipcode=01234&radius=1km

  表单数据编码格式有一个正经的MIME类型

application/x-www-form-urlencoded

  当使用POST方法提交那种顺序的表单数据时,必须”Content-Type”请求头为那一个值

  [注意]那系列型的编码并不要求HTML表单,在Ajax应用中,希望发送给服务器的很大概是二个javascript对象

  后面展示的数目变成javascript对象的表单编码情势或者是:

{find: "pizza", zipcode: 01234, radius: "1km"}

  表单编码在Web上这么广阔应用,同时兼有服务器端的编制程序语言都能博得特出的支撑,所以非表单数据的表单编码平时也是不难达成的业务

  上边代码浮现了哪些兑现目的属性的表单编码

function encodeFormData(data){
    if (!data) return "";    //一直返回字符串
    var pairs = [];            //用于保存名值对
    for(var name in data){ 
        if (!data.hasOwnProperty(name)){
            continue;        //跳过继承属性
        }
        if (typeof data[name] === "function"){
            continue;         //跳过方法 
        }
        var value = data[name].toString();    //把值转换成字符串
        name = encodeURIComponent(name.replace("%20", "+")); //编码名字
        value = encodeURIComponent(value.replace("%20", "+"));//编码值
        pairs.push(name + "=" + value); // 存入名值对 
    }
    return pairs.join('&'); //返回使用'&'连接的名值对
} 

var data = {name:'小火柴',age:28,sender:'male'};
//name=%E5%B0%8F%E7%81%AB%E6%9F%B4&age=28&sender=male    
console.log(encodeFormData(data));    

 

表单连串化

  随着Ajax的现身,表单连串化已经化为一种普遍需要。在javascript中,可以使用表单字段的type属性,连同name和value属性一起落实对表单的种类化。在编制代码在此之前,有必须先搞了然在表单提交时期,浏览器是如何将数据发送给服务器的

  壹 、对表单字段的名目和值举办UPAJEROL编码,使用和号(&)分隔

  ② 、不发送禁止使用的表单字段

  ③ 、只发送勾选的复选框和单选按钮

  4、不发送type为”reset”和”button”的按钮

  伍 、多选选择框中的每种选中的值単独三个条文

  陆 、在单击提交按钮提交表单的情形下,也会发送提交按钮;不然,不发送提交按钮。也包涵type为”image”的<input>成分

  柒 、<select>元素的值,正是选中的<option>成分的value天性的值。要是<option>元素没有value脾气,则是<option>成分的文本值

  在表单类别化进度中,一般不带有其余按钮字段,因为结果字符串很恐怕是由此任何艺术交给的。除此之外的其他上述规则都应有服从

  在上面表单类别化serialize()函数中,首先定义了一个名为parts的数组,用于保存将要创制的字符串的依次部分。然后,通过for循环迭代每种表单字段,并将其保存在田野同志变量中。在获得了一个字段的引用之后,使用switch语句检查和测试其type属性

  连串化进度中最麻烦的正是<select>成分,它或者是单选框也说不定是多选框。为此,须要遍历控件中的每一个精选,并在对应选项被入选的情况下向数组中添加一个值。对于单选框,只大概有2个当选项,而多选框则可能有零或多个当选项。那里的代码适用于这二种选拔框,至于可挑选的数据则是由浏览器控制的。在找到多少个入选项之后,要求规定使用什么值。假使不设有value本性,大概虽然存在该特性,但值为空字符串,都要使用选择的公文来取代。为检査那一个特点,在DOM包容的浏览器中必要运用hasAttribute()方法,而在IE7-中要求动用脾性的specified属性

  假设表单中涵盖<田野(field)set>成分,则该因素会并发在要素集合中,但从没type属性。因而,假使type属性未定义,则不必要对其开始展览体系化。同样,对于种种按钮以及文件输入字段也是那般(文件输入字段在表单提交进程中包含文件的剧情;可是,那几个字段是无能为力模拟的,连串化时相似都要不经意)

  对于单选按钮和复选框,要检查其checked属性是还是不是棉被服装置为false,假使是则脱离switch语句。要是checked属性为true,则继续执行default语句,即将当前字段的名目和值举办编码,然后添加到parts数组中。函数的结尾一步,便是应用join()格式化整个字符串,也正是用和号来分隔各种表单字段

  最后,serialize()函数会以査询字符串的格式输出连串化之后的字符串

function serialize(form){        
    var parts = [],field = null,option,optValue;
    for (var i=0, len=form.elements.length; i < len; i++){
        field = form.elements[i];
        switch(field.type){
            //单选或多选的<select>控件
            case "select-one":
            case "select-multiple":
                //如果该<select>控件设置为name属性  
                if (field.name.length){
                    for (var j=0,optLen = field.options.length; j < optLen; j++){
                        //选择<option>控件
                        option = field.options[j];
                        //如果该<option>控件被选中
                        if (option.selected){
                            optValue = "";
                            //测试<option>控件的value属性,如果没有设置,则读取其text属性
                            //IE7-浏览器不支持hasAttribute()
                            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:     //fieldset
            case "file":        //file input
            case "submit":      //submit button
            case "reset":       //reset button
            case "button":      //custom button
                break;                
            case "radio":       //radio button
            case "checkbox":    //checkbox
                //如果没有选中项
                if (!field.checked){
                    break;
                }                  
            default:              
                if (field.name.length){
                    parts.push(encodeURIComponent(field.name) + "=" + encodeURIComponent(field.value));
                }
        }
    }        
    return parts.join("&");
}

<form name="form" action="test.php">
    <input type="text" value="123" name="text">
    <select name="color"  multiple>
        <option>红</option>
        <option>绿</option>
        <option>蓝</option>
    </select>
    <input type="radio" name="gender" id="male" value="male"><label for="male">男</label>
    <input type="radio" name="gender" id="female" value="female"><label for="female">女</label>
    <input type="checkbox" name="time" value="12" id="t12"><label for="t12">12小时</label>
    <input type="checkbox" name="time" value="24" id="t24"><label for="t24">24小时</label>
    <button name="btn" type="button">按钮</button>
</form>
<div id="result"></div>
<script>
var oForm = document.forms.form;
oForm.onchange = function(e){
    e = e || event;
    result.innerHTML = serialize(form);
}
</script>

 

FormData

  当HTML表单同时含有文件上传成分和任何因素时,浏览器不能应用普通的表单编码而必须利用称为“multipart/form-data”的特种Content-Type来用POST方法提交表单。那种编码包蕴运用长“边界”字符串把请求主体分离成四个部分。对于文本数据,手动创设“multipart/form-data”请求主体是或然的,但很复杂

  XMLHttpRequest
2级为此概念了FormData类型。FormData为系列化表单以及开创与表单格式相同的数据(用于通过XHWrangler传输)提供了便于

  [注意]IE9-浏览器不援救

【构造函数】

new FormData (form? : HTMLFormElement)

  可选参数form表示2个HTML表单成分,可以涵盖其他方式的表单控件,包含文件输入框

【append()】

  append()方法用于给当下FormData对象添加一个键/值对

void append(DOMString name, Blob value, optional DOMString filename);
void append(DOMString name, DOMString value);

  参数值name表示字段名称;参数值value表示字段值;参数值filename(可选)用于钦定文件的文件名,当value参数被钦定为2个Blob对象或许贰个File对象时,该文件名会被发送到服务器上,对于Blob对象的话,那么些值暗中同意为”blob”

【其余不常用艺术】

  get():通过get(key)/getAll(key)来取得相应的value

  set():通过set(key,value)修改数据,假诺内定的key不存在则猛增一条,假诺存在,则修改对应的value值

  has():通过has(key)来判断是还是不是对应的key值

  delete():通过delete(key)来删除数据

  [注意]上述五个不常用方法,IE浏览器都不接济

var oData1 = new FormData();
console.log(oData1.has('a'));//false
oData1.append('a',1);
console.log(oData1.has('a'));//true
console.log(oData1.get('a'));//1
oData1.set('a',2);
oData1.append('a',1);
console.log(oData1.get('a'));//2
console.log(oData1.getAll('a'));//["2", "1"]
oData1.delete('a');
console.log(oData1.get('a'));//null

<form action="#" name="form1">
    <input type="text" value="1" name="a">
</form>
<script>
var oData1 = new FormData(document.forms.form1);
console.log(oData1.has('a'));//true
console.log(oData1.get('a'));//1
oData1.append('a',2);
console.log(oData1.get('a'));//1
console.log(oData1.getAll('a'));//['1','2']
</script>

  一般地,大家运用FormData()构造函数创立FormData对象,然后按需数十四回调用那么些指标的append()方法把个人“部分”(可以是字符串、File或Blob对象)添加到请求中。最终,把FormData对象传递给send()方法,通过XH汉兰达对象将其发送到服务器

  [注意]multipart/form-data只可以用于post方式

<form action="#" name="form1">
<select name="a">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>
</form>
<div id="result"></div>
<script>
var oForm = document.forms.form1;
oForm.onchange = function(){
    //创建xhr对象
    var xhr;
    if(window.XMLHttpRequest){
        xhr = new XMLHttpRequest();
    }else{
        xhr = new ActiveXObject('Microsoft.XMLHTTP');
    }
    //异步接受响应
    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4){
            if(xhr.status == 200){
                //实际操作
                result.innerHTML = xhr.responseText;
            }
        }
    }
    //发送请求
    xhr.open('post','t1.php' ,true);
    xhr.send(new FormData(form1)); 
}
</script>

相关文章