jQuery serialize


jQuery serialize模塊是對象數組序列化模塊。

首先我們先看一下《JavaScript高級程序設計》中的序列化函數,專門用於form參數序列化的。

 

serialize函數

function serialize(form){
    var parts = [],
        field = null,
        i,
        len,
        j,
        optLen,
        option,
        optValue;
        
    for(i = 0, len = form.elements.length; i < len; i++){
        field = form.elements[i];
        
        switch(field.type){
            case "select-one":
            case "select-multiple":
            
            if(field.name.length){
                for(j = 0, optLen = field.options.length; j < optLen; j++){
                    option= field.options[j];
                    if(option.selected){
                        optValue = "";
                        if(option.hasAttribute){
                            optValue = (option.hasAttribute("value")) ? 
                                        option.value : ooption.text);
                        }else{
                            optValue = (option.attributes["value"].specified ?
                                        option.value : option.text);
                        }
                        parts.push(encodeURIComponent(field.name) + "=" +
                                    encodeURIComponent(optValue));
                    }
                }
            }
            
            case undefined:
            case "file":
            case "submit":
            case "reset":
            case "button":
                break;
                
            case "radio":
            case "checkbox":
                if(!fied.checked){
                    break;
                }
                
            default:
                if(field.name.length){
                    parts.push(encodeURIComponent(field.name) + "=" +
                                encodeURIComponent(field.value));
                }
                
            }
        
        }
        return parts.join("&");
    }


}

這能幫我們理解下面有些操作,當然從整體實現是差不多的。

但是jQuery提供了利用遞歸將深入對象或數組內部去序列化,而該方法只能對其下一級序列化,不能再深入下去。

而且jQuery能對滿足要求對象、數組進行序列化。

 

jQuery.param

jQuery.param = function( a, traditional ) {
    var prefix,
        s = [],
        // 內部函數充填函數
        add = function( key, value ) {
            // 如果value是一個函數,運行並得到其值
            value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
            // 向數組s中推入字符串"key=value"
            s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
        };

    // 如果traditional為true,提供jQuery1.3.2以下版本兼容處理
    
    // 如果traditional沒定義
    if ( traditional === undefined ) {
        // 將traditional設置成jQuery.ajaxSettings.traditional
        traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
    }

    // 如果a數組,假設其是一個包含元素的數組
    if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
        // Serialize the form elements
        // 對a中所有元素的name和value推入s數組
        jQuery.each( a, function() {
            add( this.name, this.value );
        });

    // 否則
    } else {
        // 如果是traditional方式,則以老的方式encode(jQuery1.3.2以下版本)
        // 否則遞歸encode
        for ( prefix in a ) {
            buildParams( prefix, a[ prefix ], traditional, add );
        }
    }

    // 將s數組用&連接成字符串,將空白替換成+
    return s.join( "&" ).replace( r20, "+" );
};

jQuery.param能將所有參數序列化,提供了對jQuery1.3.2一下版本不深入對象內部的兼容模式。

 

buildParams函數

function buildParams( prefix, obj, traditional, add ) {
    var name;

    // 如果obj是一個數組
    if ( jQuery.isArray( obj ) ) {
        // 序列化數組所有元素
        jQuery.each( obj, function( i, v ) {
            // 如果tranditional為true,或者prefix即當前obj名字為xxx[]
            if ( traditional || rbracket.test( prefix ) ) {
                // 則v可當成常量直接推入
                add( prefix, v );
            // 否則,即prefix不是xxx[]形式,可能會xxx或者xxx[i]形式
            } else {
                // v不是常量(是數組或者對象),如果v此時不是數組或則對象,則下次可以當成是常量了,即變成xxx[]
                // 否則變成xxx[i],遞歸
                buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
            }
        });
    // 否則,非tranditional且obj是對象
    } else if ( !traditional && jQuery.type( obj ) === "object" ) {
        // 遍歷序列化
        for ( name in obj ) {
            // 遞歸,變成xxx[name]
            buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
        }

    } else {
        // 到這里,證明不是對象也不是數組,或者是traditional模式,那么直接添加吧
        add( prefix, obj );
    }
};

如果是傳統模式,則不遞歸,直接輸出,否則遞歸。 

 

jQuery.fn.serialize

jQuery.fn.serialize = function() {
    // 利用jQuery.param和jQuery.fn.serializeArray
    return jQuery.param( this.serializeArray() );
};

序列化函數,實際上是調用param來序列化。

不過先要用serializeArray組裝一下。 

 

jQuery.fn.serializeArray

jQuery.fn.serializeArray: function() {
    // 使用jQuery.fn.map遍歷所有元素
    return this.map(function(){
        // 讀取this.elements
        var elements = jQuery.prop( this, "elements" );
        // 如果elements存在則變成數組返回,否則返回this
        return elements ? jQuery.makeArray( elements ) : this;
    })
    // 過濾
    .filter(function(){
        // 得到type
        var type = this.type;
        // Use .is(":disabled") so that fieldset[disabled] works
        // 如果該元素有name屬性,並且這個元素不是:disabled
        return this.name && !jQuery( this ).is( ":disabled" ) &&
            // 如果節點名字是input、select、textarea或者keygen,
            // 並且type不是submit、button、image或reset這些可提交元素
            rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
            // 如果this.checked為true,或者不是checkbox、radio
            ( this.checked || !manipulation_rcheckableType.test( type ) );
        
        // 滿足的保留,否則過濾
    })
    // 再次map遍歷所有剩下元素
    .map(function( i, elem ){
        // 通過.val獲取elem的值
        var val = jQuery( this ).val();

        // 如果val為null
        return val == null ?
            // 則返回null
            null :
            // 否則如果是數組
            jQuery.isArray( val ) ?
                // 遍歷數組的子元素
                jQuery.map( val, function( val ){
                    // 組裝成下面形式的元素組成的數組
                    return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
                }) :
                // 返回這種形式
                { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
    }).get(); //轉成數組返回,此時不能鏈式了
};

 組裝參數對象,並過濾掉一些不需要序列化的元素。

 

jQuery.fn.map

jQuery.fn.map = function( callback ) {
    return this.pushStack( jQuery.map(this, function( elem, i ) {
        return callback.call( elem, i, elem );
    }));
};

我們可以看出其主要使用了jQuery.map來實現的。

 

jQuery.map

jQuery.map = function( elems, callback, arg ) {
    var value,
        i = 0,
        length = elems.length,
        isArray = isArraylike( elems ),
        ret = [];

    // 先看看elems是不是數組
    if ( isArray ) {
        // 遍歷數組
        for ( ; i < length; i++ ) {
            // 得到callback的返回值
            value = callback( elems[ i ], i, arg );

            // 組裝返回值數組
            if ( value != null ) {
                ret[ ret.length ] = value;
            }
        }

    // 如果不是數組,那么就當他是一個對象
    } else {
        // 遍歷其所有key
        for ( i in elems ) {
            // 得到callback的返回值
            value = callback( elems[ i ], i, arg );

            // 組裝返回值數組
            if ( value != null ) {
                ret[ ret.length ] = value;
            }
        }
    }

    // 合並所有嵌套數組
    return core_concat.apply( [], ret );
};

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM