Jquery-cache源码分析-jquery1.8.3

var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,//匹配json串
 rmultiDash = /([A-Z])/g;//匹配大写字母
jQuery.extend({//作用如其名,就是缓存数据,可以对节点或普通对象缓存数据,本对象也可以为jquery程序内部缓存数据
 cache: {},
 deletedIds: [],
 uuid: 0,
 expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),//系统内唯一的字串
 noData: {//不支持缓存的对象
  "embed": true,
  "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
  "applet": true
 },
 hasData: function( elem ) {
  elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
  return !!elem && !isEmptyDataObject( elem );
 },
 data: function( elem, name, data, pvt /* Internal Use Only */ ) {//作用是为elem对象的name属性设置或赋值
  if ( !jQuery.acceptData( elem ) ) {//若元素不接受数据则退出
   return;
  }
  var thisCache, ret,
   internalKey = jQuery.expando,//内部唯一性字段,jquery内部唯一,整个执行过程唯 一
   getByName = typeof name === "string",//是否是根据属性的名字来取或存数据
   isNode = elem.nodeType,//是否是节点
   cache = isNode ? jQuery.cache : elem,//节点则保存在jquery.cache里,否则保存在对象里
   id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;//如果是节点则从属性里取id, 否则id是jquery内部唯一id
  if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {//如果是赋值则data不能为空
   return;
  }
  if ( !id ) {//修正id的值
   if ( isNode ) {
    elem[ internalKey ] = id = jQuery.deletedIds.pop() || jQuery.guid++;//如果是节点,则为节点添加属性interalKey属性并赋值guid++;
   } else {
    id = internalKey;//如果不是节点,则直接在对象上添加属性internalKey
   }
  }
  if ( !cache[ id ] ) {//如果cache还没有id这个属性,则赋空值
   cache[ id ] = {};
   if ( !isNode ) {//如果不是节点,则添加属性toJSON空方法以分辩之
    cache[ id ].toJSON = jQuery.noop;
   }
  }
  if ( typeof name === "object" || typeof name === "function" ) {//如果name不是字串而是对象或方法,则为赋值,赋值时要注意保护已存在属性
   if ( pvt ) {//如果是内部赋值,则直接在cache[id]上赋值
    cache[ id ] = jQuery.extend( cache[ id ], name );
   } else {//如果是外部使用,则在cache[id].data上赋值
    cache[ id ].data = jQuery.extend( cache[ id ].data, name );
   }
  }
  thisCache = cache[ id ];
  if ( !pvt ) {//将当前所操作的缓存对象赋给thisCache
   if ( !thisCache.data ) {
    thisCache.data = {};
   }
   thisCache = thisCache.data;
  }
  if ( data !== undefined ) {//如果data不为空则为赋值,并对name进行驼峰化
   thisCache[ jQuery.camelCase( name ) ] = data;
  }
  if ( getByName ) {//如果name是字符串,则需要取值,未取到则尝试进行驼峰化后再取,如果没有name则输出所有数据
   ret = thisCache[ name ];
   if ( ret == null ) {
    ret = thisCache[ jQuery.camelCase( name ) ];
   }
  } else {
   ret = thisCache;
  }
  return ret;
 },
 removeData: function( elem, name, pvt /* Internal Use Only */ ) {//移除数据
  if ( !jQuery.acceptData( elem ) ) {//不支持缓存数据则直接退出
   return;
  }
  var thisCache, i, l,
   isNode = elem.nodeType,//是否是节点
   cache = isNode ? jQuery.cache : elem,//取出缓存对象的父级对象
   id = isNode ? elem[ jQuery.expando ] : jQuery.expando;//取出缓存对象对应的id,节点则是当前属性expando的值,否则是expando本身
  if ( !cache[ id ] ) {//如果父级对象的id属性为空,则不用再尝试,直接返回
   return;
  }
  if ( name ) {
   thisCache = pvt ? cache[ id ] : cache[ id ].data;//找出当前操作对象
   if ( thisCache ) {
    if ( !jQuery.isArray( name ) ) {//将name转换成数组,,方便后面统一操作
     if ( name in thisCache ) {
      name = [ name ];
     } else {
      name = jQuery.camelCase( name );
      if ( name in thisCache ) {
       name = [ name ];
      } else {
       name = name.split(" ");
      }
     }
    }
    for ( i = 0, l = name.length; i < l; i++ ) {//对数组内所有元素都进行移除操作,
     delete thisCache[ name[i] ];
    }
    if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {//如果此时缓存对象非空,则退出
     return;
    }
   }
  }
  if ( !pvt ) {//到这里说明name不存在,则全部删除缓存数据
   delete cache[ id ].data;//先用delete办法尝试删除
   if ( !isEmptyDataObject( cache[ id ] ) ) {
    return;
   }
  }
  if ( isNode ) {
   jQuery.cleanData( [ elem ], true );//如果是节点则用删除节点属性的办法删除
  } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
   delete cache[ id ];//如果浏览器支持delete删除对象的属性,或者节点不是frame,则delete删除之
  } else {
   cache[ id ] = null;//为对象直接赋空值
  }
 },
 _data: function( elem, name, data ) {//内部程序用来保存数据
  return jQuery.data( elem, name, data, true );
 },
 acceptData: function( elem ) {//是否可保存数据,1,不在枚举数组内2, 在枚举数组内但值不为true并且classid与对应值相同
  var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
  return !noData || noData !== true && elem.getAttribute("classid") === noData;
 }
});
jQuery.fn.extend({
 data: function( key, value ) {//对外的取赋值方法
  var parts, part, attr, name, l,
   elem = this[0],//先取出第一个jquery对象
   i = 0,
   data = null;
  if ( key === undefined ) {//如果key不存在,则是取出第一个jquery对象的缓存值
   if ( this.length ) {
    data = jQuery.data( elem );
    if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {//parsedAttrs属性是一个标记,记录是否处理过节点的属性
     attr = elem.attributes;
     for ( l = attr.length; i < l; i++ ) {
      name = attr[i].name;
      if ( !name.indexOf( "data-" ) ) {//从jquery.cache中取出数据,写在节点属性上
       name = jQuery.camelCase( name.substring(5) );
       dataAttr( elem, name, data[ name ] );//
      }
     }
     jQuery._data( elem, "parsedAttrs", true );//标记已处理
    }
   }
   return data;
  }//以下为key存在时的处理办法
  if ( typeof key === "object" ) {
   return this.each(function() {//在所有jquery对象上保存key,因为key是对象
    jQuery.data( this, key );
   });
  }
  parts = key.split( ".", 2 );//key可以为.分隔的字符串
  parts[1] = parts[1] ? "." + parts[1] : "";
  part = parts[1] + "!";
  return jQuery.access( this, function( value ) {
   if ( value === undefined ) {
    data = this.triggerHandler( "getData" + part, [ parts[0] ] );
    if ( data === undefined && elem ) {
     data = jQuery.data( elem, key );
     data = dataAttr( elem, key, data );
    }
    return data === undefined && parts[1] ?
     this.data( parts[0] ) :
     data;
   }
   parts[1] = value;
   this.each(function() {
    var self = jQuery( this );
    self.triggerHandler( "setData" + part, parts );
    jQuery.data( this, key, value );
    self.triggerHandler( "changeData" + part, parts );
   });
  }, null, value, arguments.length > 1, null, false );
 },
 removeData: function( key ) {//移除所有jquery对象的key属性
  return this.each(function() {
   jQuery.removeData( this, key );
  });
 }
});
function dataAttr( elem, key, data ) {
 if ( data === undefined && elem.nodeType === 1 ) {
  var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();//格式为data-ab-cc
  data = elem.getAttribute( name );
  if ( typeof data === "string" ) {
   try {
    data = data === "true" ? true ://统一data的值类型
    data === "false" ? false :
    data === "null" ? null :
    +data + "" === data ? +data :
    rbrace.test( data ) ? jQuery.parseJSON( data ) ://如果是json格式则解析之,
     data;
   } catch( e ) {}
   jQuery.data( elem, key, data );赋值
  } else {
   data = undefined;只要data不是字符串则是无效的值
  }
 }
 return data;
}
function isEmptyDataObject( obj ) {//判断obj对象是否是空,忽略空的data属性和toJSON属性
 var name;
 for ( name in obj ) {
  if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
   continue;
  }
  if ( name !== "toJSON" ) {
   return false;
  }
 }
 return true;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值