jquery源码解析:jQuery数据缓存机制详解2
上一課主要講了jQuery中的緩存機制Data構造方法的源碼解析,這一課主要講jQuery是如何利用Data對象實現有關緩存機制的靜態方法和實例方法的。我們接下來,來看這幾個靜態方法和實例方法的源碼解析:
data_user = new Data(); ? ?//對外使用的數據緩存對象
data_priv = new Data(); ? ?//內部的數據緩存對象,內部使用
jQuery.extend({ ? ? ?//在jQuery中添加靜態方法
acceptData: Data.accepts, ? //調用Data構造函數的accepts靜態方法
hasData: function( elem ) { ? ?//是否有這個屬性
return data_user.hasData( elem ) || data_priv.hasData( elem );
},
data: function( elem, name, data ) {
return data_user.access( elem, name, data );
},
removeData: function( elem, name ) {
data_user.remove( elem, name );
},
_data: function( elem, name, data ) { ? ?//_代表私有的方法,不對外
return data_priv.access( elem, name, data );
},
_removeData: function( elem, name ) {
data_priv.remove( elem, name );
}
});
靜態方法,是直接調用Data原型上的方法,而上一課已經詳細講解了這個Data的原型,可以參照上一課。而在jQuery緩存系統中,我們經常使用的就是以下這幾個實例方法:
jQuery.fn.extend({ ?//在jQuery原型上添加實例方法
? data: function( key, value ) { ? //一個參數時是獲取數據,兩個參數時是設置數據?
var attrs, name,
elem = this[ 0 ], ?//找到一組元素中的第一個,如果是獲取操作,只獲取一個元素,如果是設置,就設置這一組元素
i = 0,
data = null;
if ( key === undefined ) { ?//當不傳入參數時,就代表取這個元素的所有數據,比如:$("div").data();
if ( this.length ) { ? //如果有元素
data = data_user.get( elem ); ?//獲取這個元素的數據
//下面這一段代碼是來處理HTML5中的自定義屬性data-xxx的。比如:<div id="div1" data-chao-ji="dan"></div>,$("#div1")[0].dataset.chaoJi等于"dan"(HTML5寫法)。$("#div1").data("chaoJi")等于"dan"。jQuery緩存系統會把HTML5自定義屬性data-xxx這種格式的數據自動緩存起來。
if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) {//元素是否是Element,元素是否有hasDataAttrs屬性,第一次是沒有的,也就是undefined。data_priv是內部使用的Data對象,不會影響到外部使用的Data對象data_user。
attrs = elem.attributes; ?//獲取元素所有的屬性
for ( ; i < attrs.length; i++ ) {
name = attrs[ i ].name; ? ? //得到每一個屬性的名字
if ( name.indexOf( "data-" ) === 0 ) { ? ?//如果元素中的屬性名有data-開頭的字符串,就進入到if語句
name = jQuery.camelCase( name.slice(5) ); ? //取data-后面的字符串,也就是chao-ji,然后轉駝峰格式,也就是變成chaoJi。
dataAttr( elem, name, data[ name ] ); //把data-開頭的屬性名的值添加到緩存系統中
}
}
data_priv.set( elem, "hasDataAttrs", true ); //設置此元素的hasDataAttrs屬性值為true
}
}
return data;
}
if ( typeof key === "object" ) { ?//比如:$("#div1").data({name:"chaojidan",age:"25"});
return this.each(function() { ?//對每個元素,都在數據緩存中設置json中的屬性值
data_user.set( this, key );
});
}
return jQuery.access( this, function( value ) { ? ?//access的第一個參數是所有元素,第二個參數是回調,第三個參數是key值,第四個參數是value值。第五個參數的作用是來決定回調是用來設置數據還是獲取數據的(true代表設置操作,false代表獲取操作)。第六個參數和第七個參數是內部使用的,我們不用管。
var data,
camelKey = jQuery.camelCase( key );
if ( elem && value === undefined ) { ? //如果value為空的話,就代表參數只有一個,那么arguments。length=1 >1,返回false,因此代表獲取操作,獲取元素elem在緩存系統中的key屬性值
data = data_user.get( elem, key ); ? //獲取數據
if ( data !== undefined ) { ? //如果找到,就直接返回
return data;
}
data = data_user.get( elem, camelKey ); ? //如果沒找到,就再找key的駝峰方式的屬性值,比如:$("#div1").data("name-age"),它會先找name-age這種屬性名的值,如果沒找到,就找nameAge這種屬性名的值。
if ( data !== undefined ) {
return data;
}
data = dataAttr( elem, camelKey, undefined ); //如果都沒找到,就找HTML5自定義屬性data-xxx的值,比如:元素div上的data-name-age的屬性值。
if ( data !== undefined ) {
return data;
}
return;
}
this.each(function() { ? //如果value存在,就代表是設置操作。就循環所有元素,對每個元素都設置
var data = data_user.get( this, camelKey ); //先去緩存系統中取key的駝峰形式的屬性值
data_user.set( this, camelKey, value ); ? //然后把值設置給key的駝峰形式的屬性名
if ( key.indexOf("-") !== -1 && data !== undefined ) { ?//如果key包含"-",并且之前取到的key的駝峰形式的屬性值存在,那么就把此駝峰形式的屬性值,賦給key這個屬性名。舉個例子:$("#div1").data("name-age","1"),這時緩存系統中會存儲nameAge:1,然后我再$("#div1").data("name-age","2"),這時data = 1,nameAge:2,進入if語句,緩存系統會再存儲name-age:1。
data_user.set( this, key, value );
}
});
}, null, value, arguments.length > 1, null, true );
},
removeData: function( key ) { ? ?//刪除數據
return this.each(function() {
data_user.remove( this, key );
});
}
});
function dataAttr( elem, key, data ) { ? //key=chaoJi
var name;
if ( data === undefined && elem.nodeType === 1 ) { ? //首先判斷數據緩存中是否有此名字的屬性值,如果沒有,并且元素是Element,就進入if語句。如果數據緩存中已經有了此名字的屬性值,那么就直接返回這個值。意思就是:當HTML5的data-xxx的屬性名xxx與jQuery通過data方法添加到數據緩存的屬性名xxx是一樣的,那么你通過data方法訪問時,獲取到的值是數據緩存中的xxx屬性值,而不是HTML5的data-xxx的屬性值,只有數據緩存沒有這個xxx的屬性值時,才會去取HTML5的data-xxx的屬性值。
name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); ?//rmultiDash = /([A-Z])/g;取大寫字母,也就是J,然后用-J代替J,這時key是chao-Ji,然后轉小寫,因此變成chao-ji。name= "data-chao-ji"
data = elem.getAttribute( name ); ? //得到元素上的這個HTML5自定義屬性的屬性值"dan"
if ( typeof data === "string" ) { ? ?//如果屬性值是字符串就保存到緩存系統
try {
data = data === "true" ? true : ?
data === "false" ? false :
data === "null" ? null :
+data + "" === data ? +data : ?//如果是數字字符串,就存入數字
rbrace.test( data ) ? JSON.parse( data ) : ?//rbrace判斷是否是一個json字符串,如果是就解析成json。
data; ? //如果是字符串,就直接返回字符串
} catch( e ) {}
data_user.set( elem, key, data );
} else { ? //如果不是字符串就直接返回undefined,也就是說HTML5的data-xxx的屬性值只能是一個字符串,如果不是,那么你通過jQuery的data(xxx)方法獲取時,是獲取不到的,返回undefined。
data = undefined;
}
}
return data;
}
緩存系統到此結束,下一課將講解隊列Queue的實現原理。
大家不要以為這就是源碼粘貼,其實里面的注釋是非常重要的,有些復雜的,我都會舉例子說明,因此看起來不會很難。請看里面的注釋。
?
?
?
加油!
轉載于:https://www.cnblogs.com/chaojidan/p/4181630.html
總結
以上是生活随笔為你收集整理的jquery源码解析:jQuery数据缓存机制详解2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【HDOJ】2577 How to Ty
- 下一篇: web页面事件无响应,元素点击不到