`
jianfulove
  • 浏览: 120285 次
  • 性别: Icon_minigender_1
  • 来自: 湛江
社区版块
存档分类
最新评论
阅读更多

    网上有很多教你怎么使用jQuery.data(..)来实现数据缓存,但有两个用户经常使用的data([key],[value])和jQuery.data(element,[key],[value])几乎没有什么文章说清楚它们两的区别,所以我用到了,研究下分享给大家。
$("").data([key],[value])与jQuery.data(element,[key],[value])的区别
这两个函数都是用来在元素上存放数据也就平时所说的数据缓存,都返回jQuery对象,当时我分别在使用它俩的时候真的吓我一跳,区别可大了,真是不用不知道,一用吓一跳。看例子先吧,后再根据源代码分析。

<div id="test2" onclick="test()">test2</div>
		  <div id="abc3" onclick="test()">test3</div>
		  <div id="test" onclick="test()">test</div>
		  <p id="ttt">aaaa</p>
	<script>
	  $(document).ready(function(){
        $("#test").click(function(){
        alert("JQUERY");
     
	 var e=$("div");//定义了两jquery对象
	 var w=$("div");//e是不等于w的。

     //首先使用data([key],[value])用法。
      $(e).data("a","aaaa");//分别在e和w上保存Key一样的数据,
	  $(w).data("a","wwww");// 看它是否会覆盖前面的,虽然是保存在不同对象上。
      alert($(e).data("a"));//你猜到答案了吗,里输出是wwww;是不是有点意外?
	  alert(e===w)//false
	  alert($(w).data("a"));//这里也是wwww;
	 
  //使用jQuery.data(element,[key],[value])来存放数据。
      $.data(e,"b","cccc");//分别在e和w上保存Key一样的数据,
	  $.data(w,"b","dddd");// 看它是否会覆盖前面的,虽然是保存在不同对象上。
	  alert($.data(e,"b"));//应该你能猜答案吧,输出cccc
      alert($.data(w,"b"));//这输出dddd
    
         });
     });
</script>

    看了上面的例子是不是发现data([key],[value])与jQuery.data(element,[key],[value])两个根本就不一样了对吧?它们之间到底有没有关系呢。怎么data([key],[value])会覆盖前面key相同的值呢?
而jQuery.data(element,[key],[value])只要是绑定到不同的对象上都不会造成覆盖。是这样吗?那来研究下它们的源代码吧。

先看jQuery.data(element,[key],[value])源代码。

jQuery.extend({
	cache: {},

	// Please use with caution
	uuid: 0,

	// Unique for each copy of jQuery on the page
	// Non-digits removed to match rinlinejQuery
	expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),

	....
	data: function( elem, name, data, pvt /* Internal Use Only */ ) {
	// 是否可以附加数据,不可以则直接返回
		if ( !jQuery.acceptData( elem ) ) {
			return;
		}

		var privateCache, thisCache, ret,
		    //jQuery.expando这是一个唯一的字符串,是这介jquery对象产生的时候就生成了。
			internalKey = jQuery.expando,
			getByName = typeof name === "string",

			// 必须区分处理DOM元素和JS对象,因为IE6-7不能垃圾回收对象跨DOM对象和JS对象进行的引用属性
			isNode = elem.nodeType,

			 // 如果是DOM元素,则使用全局的jQuery.cache 
			 // 如果是JS对象,则直接附加到对象上
			cache = isNode ? jQuery.cache : elem,

			// Only defining an ID for JS objects if its cache already exists allows
			// the code to shortcut on the same path as a DOM node with no cache
			id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,
			isEvents = name === "events";

		 // 避免做更多的不必要工作,当尝试在一个没有任何数据的对象上获取数据时
		// 对象没有任何数据,直接返回
		if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
			return;
		}
        // id不存在的话就生成一个
		if ( !id ) {
			// Only DOM nodes need a new unique ID for each element since their data
			// ends up in the global cache
			if ( isNode ) {
			 // 如果是DOM元素则在元素上产生唯一的ID 并且以jQuery.expando
			 //为属性值为id保存在elem元素上,以便以后再根据jQuery.expando来查找ID。
				elem[ internalKey ] = id = ++jQuery.uuid;
			} else {
			// JS对象则直接使用jQuery.expando,既然是直接附加到对象上,又何必要id呢?
              // 避免与其他属性冲突!
				id = internalKey;
			}
		}

        //// 当我们试着访问一个键是否含有值的时候,如果不存在jQuery.cache[id]值,
        // 初始化jQuery.cache[id]值 为一个空对象{}
		if ( !cache[ id ] ) {
			cache[ id ] = {};
 
			if ( !isNode ) {
				cache[ id ].toJSON = jQuery.noop;
			}
		}

		// An object can be passed to jQuery.data instead of a key/value pair; this gets
		// shallow copied over onto the existing cache
		// data是接收对象和函数,浅拷贝
		if ( typeof name === "object" || typeof name === "function" ) {
			if ( pvt ) {
				cache[ id ] = jQuery.extend( cache[ id ], name );
			} else {
				cache[ id ].data = jQuery.extend( cache[ id ].data, name );
			}
		}
        / 存储对象,存放了所有数据的映射对象
		privateCache = thisCache = cache[ id ];

		// jQuery data() is stored in a separate object inside the object's internal data
		// cache in order to avoid key collisions between internal data and user-defined
		// data.
		 // jQuery内部数据存在一个独立的对象(thisCache.data==thisCache[ internalKey ])
		  //上,为了避免内部数据和用户定义数据冲突
		if ( !pvt ) {
              // 存放私有数据的对象不存在,则创建一个{}
			if ( !thisCache.data ) {
				thisCache.data = {};
			}
             // 使用私有数据对象替换thisCache
			thisCache = thisCache.data;
		}
       // 如果data不是undefined,表示传入了data参数,则存储data到name属性上
		if ( data !== undefined ) {
		// jQuery.camelCase( name )作用是如果传入的是object/function,不做转换,
		//只有传入的name是字符串才会转换。所以最终保存下来的是key/value对;
			thisCache[ jQuery.camelCase( name ) ] = data;
		}

		//从这以后下面的代码都是处理data: function( elem, name)data为空,求返回值data的情况了。

		if ( isEvents && !thisCache[ name ] ) {
			return privateCache.events;
		}

	   // 如果name是字符串,则返回data
       // 如果不是,则返回整个存储对象
		if ( getByName ) {

			// First Try to find as-is property data
			ret = thisCache[ name ];

			// Test for null|undefined property data
			if ( ret == null ) {

				// Try to find the camelCased property
				ret = thisCache[ jQuery.camelCase( name ) ];
			}
		} else {
			ret = thisCache;
		}

		return ret;
	},
	............
	});

请看图。

 

 

 看jQuery.data(element,[key],[value])源代码后可以知道,每一个element都会有自己的一个{key:value}对象保存着数据,所以新建的对象就算有key相同它也不会覆盖原来存在的对象key所对应的value,因为新对象保存是是在另一个{key:value}对象中。

         接下来要分析data([key],[value])源代码使用到了each(callback),在分析它之前先看下each(callback)用法和源代码。

    <div id="test2" onclick="test()">test2</div>
		  <div id="abc3" onclick="test()">test3</div>
		  <div id="test" onclick="test()">test</div>
		  <p id="ttt">aaaa</p>
	<script>
	  $(document).ready(function(){
        $("#test").click(function(){
        alert("JQUERY");

        var i=0;
		$("#abc3").each(function() {
		alert(++i);//只输出1;因为只有一个<div id="abc3">
		});
     alert("----");
	    var j=0;
		$("div").each(function() {
		alert(++j);//分别输出1,2,3;因为有三个<div>所以循环三遍
		});
	 });
   });
	</script>



现在来看each方法的具体实现如下:
jQuery.fn = jQuery.prototype = {
    each: function( callback, args ) {
        return jQuery.each( this, callback, args );
    }
}

可以看到它返回的是全局的each方法,并且将自身jQuery对象做为参数给它,全局的each方法的具体实现如下:
// args 作为内部成员的调用来使用
each: function( object, callback, args ) {
    var name, i = 0, length = object.length;  // 当object为jQuery对象时,length非空

    if ( args ) {
        if ( length === undefined ) {
            for ( name in object )
                if ( callback.apply( object[ name ], args ) === false )
                    break;
        } else
            for ( ; i < length; )
                if ( callback.apply( object[ i++ ], args ) === false )
                    break;  
    // 以下是客户端程序进行调用
    } else {
        if ( length === undefined ) {
            for ( name in object )
                if ( callback.call( object[ name ], name, object[ name ] ) === false )
                    break;
        } else
            // i表示索引值,value表示DOM元素
            for ( var value = object[0];
                i < length && callback.call( value, i, value ) !== false; 
                value = object[++i] ){}
    }  

    return object;
}

 现在我们关注下 for ( var value = object[0]; i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} 这句代码;其中object[0]取得jQuery对象中的第一个DOM元素,通过for循环,
得到遍历整个jQuery对象中对应的每个DOM元素,通过callback.call( value,i,value); 将callback的this对象指向value对象,并且传递两个参数,i表示索引值,value表示DOM元素;其中callback是类似于 function(index, elem) { } 的方法。所以就得到 $("").each(function(index, elem){ });

 

 再来看看data([key],[value])的源代码。

 

jQuery.fn.extend({
	data: function( key, value ) {
		var parts, part, attr, name, l,
			elem = this[0],
			i = 0,
			data = null;

		// Gets all values
		if ( key === undefined ) {
			.....//处理没有Key的情况,这里不是我们要讨论的

			return data;
		}

		// Sets multiple values
		if ( typeof key === "object" ) {
			return this.each(function() {
				jQuery.data( this, key );
			});
		}

		parts = key.split( ".", 2 );
		parts[1] = parts[1] ? "." + parts[1] : "";
		part = parts[1] + "!";

		return jQuery.access( this, function( value ) {

			if ( value === undefined ) {
				。。。//这里是没有value时,是索取返回值的情况,这不是我们讨论
			}

			parts[1] = value;

           //如果我使用用$("div").data("a","aaa")),下面调用each前的this指的是$("div")这返回的对象,
			this.each(function() {//注意了,这里是以每一个匹配的元素作为上下文来执行一个函数
				var self = jQuery( this );

				self.triggerHandler( "setData" + part, parts );

				//这里在元素上存放数据,本质还是委托data(element,[key],[value])来做的。
			     //看前面有分析过了。
			     //下面data( this, key, value )里的this指的是遍历整个jQuery对象中对应的每个DOM元素
			     //$("div")它对应页面中一个<div>数组。
			jQuery.data( this, key, value );//这名句会被循环多次执行,也就是保存数据。
				//这里就是核心一句话。但要清楚看上面了它是在each(functipn(){})中的。
				self.triggerHandler( "changeData" + part, parts );
			});
		}, null, value, arguments.length > 1, null, false );
	},
//在元素上移除存放的数据。具体实现如下: 
	removeData: function( key ) {
		return this.each(function() {
			jQuery.removeData( this, key );
		});
	}
});

 

 

 如果对于data([key],[value])的源代码不是很了解,好吧,我就用一个例子来模仿实现它吧。

<div id="test2" onclick="test()">test2</div>
		  <div id="abc3" onclick="test()">test3</div>
		  <div id="test" onclick="test()">test</div>
		  <p id="ttt">aaaa</p>
	<script>
	  $(document).ready(function(){
        $("#test").click(function(){
        alert("JQUERY");

        var i=0;
		$("#abc3").each(function() {
		alert(++i);//只输出1;因为只有一个<div id="abc3">
		});
     alert("----");
	    var j=1;
		$("div").each(function() {//以每一个匹配的元素作为上下文来执行这个函数

                    $.data(this,"a","wwww");//这里的this就是指$("div"),
					                                   //分别遍历每一个匹配的元素给它们每一个对象{}都保存一个key/value
					alert(j++);//分别输出1 ,2 ,3 因为有三个<div>元素
		});
		 alert($("#test").data("a"));//返回wwww, 
		   //是不是很惊呀,我没有保存在它身上啊,怎么也有值,很明显是它是查这个div节点上有没有,
		   //肯定是有值了,因为上面给循环保存在div这Dom结点上了。
		 alert($("#test")===$("div"));//false证明两新建的对象不是同一个。

		 alert($("div").data("a"));//返回wwww,
		 //这里也是一样因为是div节点上都保存了"a"="wwww"这样一个键值对了。
		 });
       });
	</script>

 现在对data([key],[value])与jQuery.data(element,[key],[value])都有了解了吧,如果还是半懂,再回头多看一遍,耐心地理解一下。其实表面上很不一样。但本质上还是有联系的,现在明白原理后就可以请放心地使用了。jQuery.data(element,[key],[value])只把数据绑定到参数element节点上。data([key],[value])
    如$("div").data("a","aaaa")它是把数据绑定每一个匹配div节点的元素上。
    附加说明下,文中所分析用到的是jquery-1.7.2.js的源代码。如果你想了解更多请自行去下载哈。

 

 

  • 大小: 42 KB
6
0
分享到:
评论
5 楼 逆寒刀 2014-03-17  
颇为耐心的一片文章,很细致,谢谢分享
4 楼 ysyong 2013-11-04  
这文章太啰嗦了,直接一个$.each不就说明了问题吗?
3 楼 zyc199144 2013-09-16  
谢谢分享,学习了。
2 楼 jianfulove 2013-05-21  
aboutibm 写道


你不要这样无聊好不好,我发文章的时候是2013-04-05 15:20。而http://www.software8.co/wzjs/jquery/3731.html发的是2013-04-06 07:49  ,你却说我抄他的,是他直接把我的抄袭了,又没有标出转载我的文章,你是不是和他一伙的,再这样胡闹,我会找到你告你侵犯我的权利。
1 楼 aboutibm 2013-05-21  

相关推荐

    jQuery 数据缓存data(name, value)详解及实现

    数据缓存通过data()方法实现,它允许开发者在jQuery对象上绑定任意类型的数据,并通过一个简单的API进行存取。 ### 数据缓存的背景和作用 在没有数据缓存机制之前,开发者可能会将数据存储在全局变量中,或者创建...

    JquerySession-JqueryCookie缓存插件(实例+注释说明)

    **jQuery Session & Cookie缓存插件详解** 在Web开发中,数据存储是不可或缺的一部分,而Session和Cookie作为客户端与服务器之间交互数据的重要手段,经常被用于实现用户状态管理。jQuery库提供了一些方便的方法来...

    jquery.mobile主要文件

    5. **优化策略**:为了减少网络请求和提高加载速度,可以采用异步加载(ajax)页面,或者利用`data-dom-cache`属性缓存页面。 6. **自定义配置**:通过设置全局配置选项,如`$.mobile.pageLoadErrorMessage`,可以...

    jQuery-ajax.rar_jquery

    4. **AJAX缓存**:通过`cache`参数可以开启或关闭AJAX请求的缓存,`cache: false`将禁用浏览器的默认缓存。 5. **局部变量**:在`.ajax()`的设置对象中,可以通过`context`参数指定回调函数的上下文,这样在回调中...

    Jquery中$.ajax()方法参数详解

    6. data:该参数可以是对象或字符串,用于发送到服务器的数据。GET请求会将这些数据附加在URL后,而POST请求则在请求体中发送。对象形式的数据会自动转换为适合HTTP请求的字符串格式。对于POST请求,数据默认以...

    jQuery中异步交互技术详细指南

    jQuery库提供了强大的异步交互API,使得开发者能够轻松地与服务器进行数据交换,而无需深入了解复杂的AJAX(Asynchronous JavaScript and XML)原理。本文将深入探讨jQuery中的异步交互技术,特别是`jQuery.ajax()`...

    jquery 的ajax用法

    **jQuery的Ajax用法详解** 在Web开发中,Ajax(Asynchronous JavaScript and XML)技术允许我们在不刷新整个页面的情况下与服务器进行数据交互,极大地提升了用户体验。jQuery库简化了JavaScript中的Ajax操作,使得...

    jQuery AutoComplete使用实例

    **jQuery AutoComplete 使用详解** jQuery AutoComplete 是一个非常流行的 jQuery 插件,它为输入框提供了自动补全功能,能够极大地提升用户体验。这个插件基于 jQuery 库,因此需要先引入 jQuery 才能使用。在本文...

    jQuery-1.6-api

    jQuery 1.6的`$.ajax()`方法提供了更丰富的配置选项,比如`dataType`可以指定返回数据的类型,`cache`控制是否缓存响应,`success`、`error`等回调函数让异步处理更加灵活。 7. **动画效果的控制** jQuery 1.6中...

    对jquery的ajax进行二次封装以及ajax缓存代理组件:AjaxCache详解

    AjaxCache 组件维护了一个简单的缓存对象 `cache`,并提供了 `get` 方法。这个方法首先检查缓存中是否有对应请求的结果,如果存在且未过期,则直接返回缓存数据;否则,将发起 AJAX 请求获取最新数据,同时更新缓存...

    jquery与ajax调用,有代码 , 有说明,使ajax调用简单

    **jQuery与Ajax调用详解** 在Web开发中,jQuery与Ajax的结合使用极大地简化了异步数据交互的过程,使得前端可以高效地与服务器进行通信,而无需刷新整个页面。本教程将详细介绍如何利用jQuery实现Ajax调用,并通过...

    JQuery中$.ajax()方法参数详解

    在JavaScript和Web开发中,jQuery库提供了一个强大的功能,即$.ajax()方法,它使得开发者能够轻松地实现异步数据交换,从而创建出更富交互性的网页应用。AJAX(Asynchronous JavaScript and XML)的核心在于利用...

    jquery mobike

    2. **页面预加载**:使用 `data-dom-cache="true"` 缓存页面,减少加载时间。 3. **自定义主题**:通过在线工具(如 jQuery ThemeRoller)定制个性化主题。 4. **媒体查询**:利用 CSS3 媒体查询实现响应式设计,...

    jQuery1.3 jQuery1.3

    **jQuery1.3详解** jQuery,作为一款广泛使用的JavaScript库,极大地简化了DOM操作、事件处理、动画设计以及Ajax交互。jQuery1.3是该库的一个重要版本,它在前一版本的基础上进行了许多优化和改进,提升了性能和...

    ajax cache重写

    **Ajax Cache 重写技术详解** 在Web应用中,Ajax(Asynchronous JavaScript and XML)技术被广泛用于实现页面的部分更新,提升用户体验。然而,随着应用复杂性的增加,频繁的Ajax请求可能会导致服务器负担加重,...

    jquery_ajax操作数据库

    **jQuery AJAX 操作数据库详解** jQuery 是一个广泛使用的 JavaScript 库,它极大地简化了 JavaScript 的 DOM 操作、事件处理和Ajax交互。AJAX(Asynchronous JavaScript and XML)是一种创建动态网页的技术,允许...

Global site tag (gtag.js) - Google Analytics