Dieser Artikel stellt Ihnen die Methoden der Datenoperation in jQuery und die Definition von jQuery vor. Ich hoffe, dass er für Sie hilfreich ist.
Es gibt zwei Methoden für Datenoperationen in jQuery
$().data() $.data(elem);
Die interne Implementierung ist untrennbar mit benutzerdefinierten Klassen verbundenData
Data
Data
ist in src/data/Data.js
definiert und das expando
-Attribut wird der Instanz beim Erstellen als eindeutige Kennung hinzugefügt.
function Data() { this.expando = jQuery.expando + Data.uid++; }
fügt dem Prototyp
Data.prototype = { cache: function(){ ... }, set: function(){ ... }, get: function(){ ... }, access: function(){ ... }, remove: function(){ ... }, hasData: function(){ ... } }
innerhalb von jq mehrere Methoden hinzu Verwenden Sie die Cache-Methode, um zwischengespeicherte Daten abzurufen. Übergeben Sie einen Parameterbesitzer, der das Objekt angibt, um zwischengespeicherte Daten abzurufen. Stellen Sie fest, ob für den Eigentümer ein Expando-Attribut vorhanden ist. Wenn nicht, wird angezeigt, ob der Eigentümer zum ersten Mal aufgerufen wird und das Cache-Datenobjekt initialisiert werden muss. Bestimmen Sie den Knotentyp. Wenn es sich um einen Elementknoten, einen Dokumentknoten oder ein Objekt handelt, können Sie Cache-Daten festlegen. Wenn es sich um einen Elementknoten oder Dokumentknoten handelt, verwenden Sie Objektliterale direkt für die Zuweisung. Der Attributname lautet expando und der Wert ist ein leeres Objekt. Wenn es sich um ein Objekt handelt, verwenden Sie Object.defineProperty
, um Daten dafür zu definieren. Der Attributname wird ebenfalls auf {} initialisiert. Gleichzeitig kann der Attributdeskriptor geändert und nicht aufgezählt werden.
Data.prototype.cache
cache: function( owner ) { // Check if the owner object already has a cache // 获取在owner的缓存值 var value = owner[ this.expando ]; // If not, create one if ( !value ) { value = {}; // We can accept data for non-element nodes in modern browsers, // but we should not, see #8335. // Always return an empty object. // 判断owener类型 是否能在其上调用data // 在元素节点或body或对象上可以设置data // 其他节点不设置缓存数据 if ( acceptData( owner ) ) { // If it is a node unlikely to be stringify-ed or looped over // use plain assignment // 此处为owner添加属性 key为Data对象的expando值 建立owner和Data对象之间的连接 // owner是元素节点或body if ( owner.nodeType ) { owner[ this.expando ] = value; // Otherwise secure it in a non-enumerable property // configurable must be true to allow the property to be // deleted when data is removed // owner是对象 // 为owner添加expando属性 初始化为{},同时属性描述符可以更改,不可枚举 } else { Object.defineProperty( owner, this.expando, { value: value, configurable: true } ); } } } return value; }
Verwenden Sie set
, um das Cache-Objekt zu aktualisieren. Es gibt zwei Aufrufsituationen: data(key,value)
oder data(obj)
Beim Speichern muss der Schlüsselname gespeichert werden Kamelfall-Nomenklatur.
Data.prototype.set
set: function( owner, data, value ) { var prop, cache = this.cache( owner ); // Handle: [ owner, key, value ] args // Always use camelCase key (gh-2257) if ( typeof data === "string" ) { cache[ jQuery.camelCase( data ) ] = value; // Handle: [ owner, { properties } ] args } else { // Copy the properties one-by-one to the cache object for ( prop in data ) { cache[ jQuery.camelCase( prop ) ] = data[ prop ]; } } return cache; }
Verwenden Sie get
, um das Cache-Objekt abzurufen. Beim Aufruf gibt es data(key)
und data()
. Wenn der Schlüssel nicht angegeben ist, wird das gesamte Cache-Objekt direkt zurückgegeben, andernfalls wird Cache[Schlüssel] zurückgegeben. Schlüsselnamen müssen ebenfalls in die Kamel-Schreibweise umgewandelt werden.
Data.prototype.get
get: function( owner, key ) { return key === undefined ? this.cache( owner ) : // Always use camelCase key (gh-2257) owner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ]; }
unterscheidet die Art des Aufrufs set
oder get
werden durch die Anzahl und Art der Parameter unterschieden:
Wenn der Schlüssel leer ist, wird das gesamte Cache-Objekt abgerufen
Der Schlüsseltyp ist string
und value===undefined
entspricht dem Abrufen des angegebenen Werts
Andere Anrufe sind set
, unterschieden innerhalb von set
Data.prototype.access
access: function( owner, key, value ) { // In cases where either: // // 1. No key was specified // 2. A string key was specified, but no value provided // // Take the "read" path and allow the get method to determine // which value to return, respectively either: // // 1. The entire cache object // 2. The data stored at the key // if ( key === undefined || ( ( key && typeof key === "string" ) && value === undefined ) ) { return this.get( owner, key ); } // When the key is not a string, or both a key and value // are specified, set or extend (existing objects) with either: // // 1. An object of properties // 2. A key and value // this.set( owner, key, value ); // Since the "set" path can have two possible entry points // return the expected data based on which path was taken[*] return value !== undefined ? value : key; }
Verwenden Sie remove
zum Löschen Die Eigenschaften des Cache-Objekts Beim Aufruf können Sie einen String übergeben, der den zu löschenden Schlüsselnamen darstellt, oder ein String-Array übergeben, das mehrere Schlüsselnamen enthält. Schlüsselnamen müssen ebenfalls in die Kamel-Schreibweise umgewandelt werden. Wenn keine Parameter übergeben oder übergeben werden, wird das zwischengespeicherte Datenobjekt des Eigentümers direkt gelöscht.
Data.prototype.remove
remove: function( owner, key ) { var i, cache = owner[ this.expando ]; if ( cache === undefined ) { return; } if ( key !== undefined ) { // Support array or space separated string of keys if ( Array.isArray( key ) ) { // If key is an array of keys... // We always set camelCase keys, so remove that. key = key.map( jQuery.camelCase ); } else { key = jQuery.camelCase( key ); // If a key with the spaces exists, use it. // Otherwise, create an array by matching non-whitespace key = key in cache ? [ key ] : ( key.match( rnothtmlwhite ) || [] ); } i = key.length; while ( i-- ) { delete cache[ key[ i ] ]; } } // Remove the expando if there's no more data if ( key === undefined || jQuery.isEmptyObject( cache ) ) { // Support: Chrome <=35 - 45 // Webkit & Blink performance suffers when deleting properties // from DOM nodes, so set to undefined instead // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) if ( owner.nodeType ) { owner[ this.expando ] = undefined; } else { delete owner[ this.expando ]; } } }
Stellen Sie fest, ob zwischengespeicherte Daten zum Eigentümer vorhanden sind.
Data.prototype.hasData
hasData: function( owner ) { var cache = owner[ this.expando ]; return cache !== undefined && !jQuery.isEmptyObject( cache ); }
Definition der jQuery-Methode
Nachdem Sie die interne Klasse data
definiert haben, erweitern Sie sie in /src/data.js
. hasData
, data
, removeData
, _data
, _removeData
und andere Methoden zu jQuery hinzugefügt und data
- und removeData
-Methoden zu jQuery.fn hinzugefügt.
Die in jQuery erweiterten Methoden sind alle Kapselung der Data-Methode. Beim Aufruf von $.data()
wird intern nicht zwischen set
und get
unterschieden. Im folgenden Quellcode sind Data.prototype.access
und dataUser
Instanzen von dataPriv
, die jeweils Daten zwischenspeichern und angeben, ob das jq-Objekt das Datenattribut des Elements zu Data
// $.data jQuery.extend( { hasData: function( elem ) { return dataUser.hasData( elem ) || dataPriv.hasData( elem ); }, data: function( elem, name, data ) { return dataUser.access( elem, name, data ); }, removeData: function( elem, name ) { dataUser.remove( elem, name ); }, // TODO: Now that all calls to _data and _removeData have been replaced // with direct calls to dataPriv methods, these can be deprecated. _data: function( elem, name, data ) { return dataPriv.access( elem, name, data ); }, _removeData: function( elem, name ) { dataPriv.remove( elem, name ); } } );
dataUser
hinzufügt auf Die einzigen Methoden sind und jQuery.fn
. Behandeln Sie innerhalb von data
zunächst die beiden Anrufsituationen removeData
und data
. Im ersten Fall wird das zwischengespeicherte Datenobjekt auf $().data()
zurückgegeben. Wenn es zum ersten Mal als $().data({k:v})
aufgerufen wird, wird das Datenattribut auf dem Element auch zu this[0]
hinzugefügt und < 🎜 aktualisiert >. Wenn es sich um die aufrufende Methode von $().data()
handelt, wird das jq-Objekt durchlaufen und die Cache-Daten für jeden Knoten aktualisiert. Andere Aufrufmethoden wie dataUser
und dataPriv
rufen $().data({k:v})
zur Verarbeitung auf. Das $().data(k)
hier ist nicht $().data(k,v)
. access
access
Data.prototype.access
durchläuft das jq-Objekt und löscht die zwischengespeicherten Daten auf jedem Knoten.
// $().data jQuery.fn.extend( { data: function( key, value ) { var i, name, data, elem = this[ 0 ], // elem为dom对象 attrs = elem && elem.attributes; // 节点上的属性 // Gets all values // $().data() if ( key === undefined ) { if ( this.length ) { data = dataUser.get( elem ); // elem是元素节点,且dataPriv中无hasDataAttrs时执行这个代码块里的代码 // dataPriv上的hasDataAttrs表示elem是否有data-xxx属性 // 初始化dataPriv后花括号内的代码不再执行,即以下的if内的代码只执行一次 if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { i = attrs.length; while ( i-- ) { // Support: IE 11 only // The attrs elements can be null (#14894) // 将elem的data-*-*属性以*-*转为驼峰命名方式的值为键 // 在dataAttr函数内保存到dataUser中 // 所以用$().data可以获取元素的data-*属性 但修改后dom上的属性却不变化 if ( attrs[ i ] ) { name = attrs[ i ].name; // name为data-xxx if ( name.indexOf( "data-" ) === 0 ) { // name为xxx name = jQuery.camelCase( name.slice( 5 ) ); dataAttr( elem, name, data[ name ] ); } } } // 同时将dataPriv的hasDataAttrs属性设置为真,表示已经将元素属性节点上的data属性保存到缓存对象中 dataPriv.set( elem, "hasDataAttrs", true ); } } return data; } // Sets multiple values // $().data(obj) 此处遍历this,即遍历jq对象上所有的节点,并在其设置值 if ( typeof key === "object" ) { return this.each( function() { dataUser.set( this, key ); } ); } // 除了$().data()和$().data({k:v})的其他情况 return access( this, function( value ) { var data; // The calling jQuery object (element matches) is not empty // (and therefore has an element appears at this[ 0 ]) and the // `value` parameter was not undefined. An empty jQuery object // will result in `undefined` for elem = this[ 0 ] which will // throw an exception if an attempt to read a data cache is made. // value undefined说明是获取操作 // 调用$().data(k) if ( elem && value === undefined ) { // Attempt to get data from the cache // The key will always be camelCased in Data // 从dataUser中获取 非undefined时返回 data = dataUser.get( elem, key ); if ( data !== undefined ) { return data; } // Attempt to "discover" the data in // HTML5 custom data-* attrs // dataUser中不存在key,调用dataAttr查找元素的data-*属性 // 如果存在属性,更新dataUser并返回其值 data = dataAttr( elem, key ); if ( data !== undefined ) { return data; } // We tried really hard, but the data doesn't exist. return; } // Set the data... // jq对象长度 >= 1, 调用如$().data(k,v) 遍历jq对象,为每个节点设置缓存数据 this.each( function() { // We always store the camelCased key dataUser.set( this, key, value ); } ); }, null, value, arguments.length > 1, null, true ); }, // 遍历jq对象,删除各个元素上的缓存数据 removeData: function( key ) { return this.each( function() { dataUser.remove( this, key ); } ); } } );
Unter anderem wird removeData
verwendet, um eine Typkonvertierung für das Datenattribut des Elements durchzuführen, und
dort zu aktualisieren zur gleichen Zeit. Es ist zu beachten, dass beim Aufruf im getData
-Modus das Attribut nicht in den zwischengespeicherten Daten gefunden werden kann, dataAttr
aufgerufen wird, um das Attribut im Element zu finden. dataUser
// 属性值是string 进行类型转换 function getData( data ) { if ( data === "true" ) { return true; } if ( data === "false" ) { return false; } if ( data === "null" ) { return null; } // Only convert to a number if it doesn't change the string // data转化成number再转成string后仍严格等于data if ( data === +data + "" ) { return +data; } if ( rbrace.test( data ) ) { return JSON.parse( data ); } return data; } // 获取元素的dataset中的属性,并保存到dataUser中 function dataAttr( elem, key, data ) { var name; // If nothing was found internally, try to fetch any // data from the HTML5 data-* attribute // 此处获取dataset里的值 if ( data === undefined && elem.nodeType === 1 ) { name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); // 此处将驼峰命名方式的key转化为data-*-* data = elem.getAttribute( name ); if ( typeof data === "string" ) { try { data = getData( data ); } catch ( e ) {} // Make sure we set the data so it isn't changed later // 将元素的data-*属性保存到dataUser中 dataUser.set( elem, key, data ); } else { data = undefined; } } return data; }
$().data(k, v)
Empfohlene verwandte Artikel: dataAttr
Einführung in zwei Methoden der Winkelformvalidierung
Das obige ist der detaillierte Inhalt vonMethoden der Datenoperation in jQuery und die Definition von jQuery. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!