jQuery源码分析之$.get/$.post/serialize/serializeArray方法详解

get/post源码如下:

jQuery.each( [ "get", "post" ], function( i, method ) {
	//如果第二个参数就是函数,那么表示没有传入数据!
	jQuery[ method ] = function( url, data, callback, type ) {
		// shift arguments if data argument was omitted
		if ( jQuery.isFunction( data ) ) {
			type = type || callback;
			callback = data;
			data = undefined;
		}
        //调用get那么type就是get。调用post那么type就是post!
		return jQuery.ajax({
			url: url,
			type: method,
			dataType: type,
			data: data,
			success: callback
		});
	};
});
note:

(1)get/post方法底层调用的都是ajax方法。传入的第四个参数用于指定dataType,也就是从服务器端获取的数据类型!

(2)Get方法不适合传送数据量较大的数据,同时其请求的历史信息也会保存在浏览器的缓存中,有一定的风险,而post不存在这两种情况!
 那么get请求为什么会在ajax请求中缓存:(看ajax方法中的代码片段)

           var rnoContent = /^(?:GET|HEAD)$/
           s.hasContent = !rnoContent.test( s.type );
		// Save the URL in case we're toying with the If-Modified-Since
		// and/or If-None-Match header later on
		cacheURL = s.url;
                //如果是get/head请求,执行这里的if语句,但是我们的get/post请求中无法指定cache,所以s.cache===false为假!因此就会缓存!
               //也就是说我们的URL后面不会添加当前时间,所以会缓存,这是GET请求的特点!但是post请求不管怎么样都不会缓存!
		// More options handling for requests with no content
		if ( !s.hasContent ) {//post请求这里不会执行,所以不会缓存!
			// If data is available, append data to url
			if ( s.data ) {
				cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
				// #9682: remove data so that it's not used in an eventual retry
				delete s.data;
			}
			// Add anti-cache in url if needed在$.post/$.get中无法指定cache
			if ( s.cache === false ) {
				s.url = rts.test( cacheURL ) ?
					// If there is already a '_' parameter, set its value
					cacheURL.replace( rts, "$1_=" + nonce++ ) :
					// Otherwise add one to the end
					cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
			}
		}

typeString类型

默认值:"GET"。请求类型,可以为'POST'或'GET'。注意:你也可以在此处使用诸如'PUT'、'DELETE'等其他请求类型,但它们不被所有浏览器支持。

这是codeplayer上面的说明。那么ajax方法是怎么做到默认是"GET",请看下面的片段:

	ajaxSettings: {
		url: ajaxLocation,
		type: "GET",
		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
		global: true,
		processData: true,
		async: true,
		contentType: "application/x-www-form-urlencoded; charset=UTF-8"}
note:这说明,默认的type是"GET",而且默认会执行全局事件;同时processData也是true;同时aync为true,表示默认是异步的!

processDataBoolean类型

默认值:true默认情况下,通过data属性传递进来的数据,如果是一个对象(技术上讲,只要不是字符串),都会处理转化成一个查询字符串,以配合默认内容类型 "application/x-www-form-urlencoded"。如果要发送 DOM树信息或其它不希望转换的信息,请设置为false

下面我们来看看基于get/post方法的getJSON,getScript方法:

getJSON源码:

getJSON: function( url, data, callback ) {
		return jQuery.get( url, data, callback, "json" );
	}
这也就是告诉ajax函数,dataType是"json",也就是必须把服务器端返回的数据通过parseJSON进行处理。

getScript源码:

getScript: function( url, callback ) {
		return jQuery.get( url, undefined, callback, "script" );
	}
这说明getScript调用的时候是只能传送URL和回调函数。所以data默认就是null了,同时"script"告诉ajax方法我的dataType是"script",所以在ajax方法中会经过ajaxPrefilters,ajaxTransport,ajaxConverter等多重处理,最后通过jQuery.globalEval来执行回调函数!

其实还可以通过$("<script><\/script>").appendTo("head")来加载脚本,可以通过阅读parseHTML源码来了解其中的原理!

在ajax请求或者get/post请求的时候我们需要把表单序列化,于是引入了serialize方法:

代码1:

var obj={
	name:"xxx",
	sex:"female"
}
var result1=encodeURIComponent(obj);
var result2=decodeURIComponent(result1);
alert(result1+"->"+result2);//通过encodeURIComponent把对象变成一个字符串进行传递给服务器,通过decodeURIComponent把这个对象解码!
serializeArray和serialize源码分析:

var rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
var       rsubmittable = /^(?:input|select|textarea|keygen)/i;
 var rcheckableType = (/^(?:checkbox|radio)$/i);
var   rCRLF = /\r?\n/g
jQuery.fn.extend({
	serialize: function() {
		return jQuery.param( this.serializeArray() );
	},
	serializeArray: function() {
		//如果有elements那么获取该元素的elements,否则还是自身!
		return this.map(function() {
			// Can add propHook for "elements" to filter or add form elements
			var elements = jQuery.prop( this, "elements" );
			return elements ? jQuery.makeArray( elements ) : this;
		})
		.filter(function() {
			var type = this.type;
			//filter方法里面已经是DOM元素了
			// Use .is(":disabled") so that fieldset[disabled] works
			//必须有name属性,同时该元素不是隐藏的元素,同时nodeName必须是input/select/textarea/kengen元素
			//同时该元素的type类型必须不是sumbit/button/image/reset/file类型,而且该元素的checked属性必须存在
			//如果checkded不存在,那么该元素类型必须不是checkbox/radio类型
			return this.name && !jQuery( this ).is( ":disabled" ) &&
				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
				( this.checked || !rcheckableType.test( type ) );
		})
		.map(function( i, elem ) {
			//这里面真正对元素进行处理
			//获取该元素的值,如果值是null那么返回的值就是null
			//如果该元素的值存在,同时如果该值是一个数组,那么对
			//该元素的值进行迭代,放入一个对象当中,name是元素的名称,键值是元素的值,不过该值要取值回车换行!
			var val = jQuery( this ).val();
			return val == 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();
	}
});
这里是 codeplayer网站关于该方法的说明:

serializeArray()函数用于序列化一组表单元素,将表单内容编码为一个JavaScript数组serializeArray()函数常用于将表单内容序列化为JSON对象,以便于被编码为JSON格式的字符串。该函数会将可用于提交的每个表单控件封装成一个Object对象,该对象有name和value属性,对应该表单控件的name和value属性。然后将这些Object对象封装为一个数组并返回。该函数不会序列化不需要提交的表单控件,这和常规的表单提交行为是一致的。例如:不在<form>标签内的表单控件不会被提交、没有name属性的表单控件不会被提交、带有disabled属性的表单控件不会被提交、没有被选中的表单控件不会被提交。

我来说说这里面的几个值得注意的地方:

(1)之所以不再form标签里面的表单不会提交是因为这里面用到了elements属性,该属性是[object HTMLCollection]。一般的控件是没有的,如div元素等,但是form标签是有的,所以如果调用对象是form对象就会获取该form对象下所有的表单元素,如果是div,那么不管该元素下有多少控件都找不到,因为div就没有elements属性!这就是map方法做的,让调用对象每一个DOM元素都执行这个函数

(2)调用filter方法,该方法是对前面返回的DOM集合进行筛选的过程。这个过程是苛刻的。必须有name;必须非隐藏;必须可以提交的表单控件,如input|select|textarea|keygen;同时不能是特定的控件,如:submit|button|image|reset|file;同时对于checkbox/radio而言只会序列化checked存在的元素!常规的表单会提交带有name的控件标签,这个方法不会!

(3)最后一个map方法对上面的结果进行处理,得到一个名值对,键名是控件的name属性,键值是value值!同时对"\n"全部修改为"\r\n"

(4)至于serialize方法

serialize()函数用于序列化一组表单元素,将表单内容编码为用于提交的字符串serialize()函数常用于将表单内容序列化,以便用于AJAX提交。

该方法的作用是将表单元素name/value通过encodeURIComponent进行了编码,同时形成了name1=value1&name2=value2这种字符串了,因为内部调用了jQuery.param方法!

你可能感兴趣的:(jQuery源码分析之$.get/$.post/serialize/serializeArray方法详解)