Maison  >  Article  >  interface Web  >  Méthodes d'exploitation des données dans jQuery et définition de jQuery

Méthodes d'exploitation des données dans jQuery et définition de jQuery

不言
不言original
2018-08-04 16:36:072036parcourir

Cet article vous présente les méthodes d'exploitation des données dans jQuery et la définition de jQuery. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Il existe deux méthodes pour les opérations sur les données dans jQuery

$().data()

$.data(elem);

L'implémentation interne est indissociable des classes personnaliséesData

Classes internesData

Data est défini dans src/data/Data.js, et l'attribut expando est ajouté à l'instance lors de la construction en tant qu'identifiant unique

function Data() {
    this.expando = jQuery.expando + Data.uid++;
}

Ajout de plusieurs méthodes sur le prototype

Data.prototype = {
    cache: function(){
        ...
    },
    set: function(){
        ...
    },
    get: function(){
        ...
    },
    access: function(){
        ...
    },
    remove: function(){
        ...
    },
    hasData: function(){
        ...
    }
}

Dans jq, utilisez la méthode cache pour obtenir les données mises en cache. Transmettez un paramètre propriétaire, indiquant l'objet pour obtenir les données mises en cache. Déterminez s'il existe un attribut expando sur le propriétaire. Sinon, il indique si le propriétaire est appelé pour la première fois et doit initialiser l'objet de données du cache. Déterminez le type de nœud. S'il s'agit d'un nœud d'élément, d'un nœud de document ou d'un objet, vous pouvez définir les données du cache. S'il s'agit d'un nœud d'élément ou d'un nœud de document, utilisez les littéraux d'objet directement pour l'affectation. Le nom de l'attribut est expando et la valeur est un objet vide. S'il s'agit d'un objet, utilisez Object.defineProperty pour définir les données correspondant. Le nom de l'attribut est également développé et initialisé à {}. En même temps, le descripteur de l'attribut peut être modifié et ne peut pas être énuméré.

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;
    }

Utilisez set pour mettre à jour l'objet cache, qui est divisé en deux situations d'appel : data(key,value) ou data(obj) Lors de l'enregistrement, le nom de la clé. doit être conservé dans une mallette à chameau. Nomenclature.

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;
    }

Utilisez get pour obtenir l'objet cache, il y a data(key) et data() lors de l'appel. Si la clé n'est pas spécifiée, l'intégralité de l'objet cache est renvoyée directement, sinon cache[key] est renvoyée. Les noms de clés doivent également être convertis en chameau.

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 ) ];
    }

distingue la méthode d'appel Les appels internes set ou get

se distinguent par le nombre et le type de paramètres :

  • Lorsque la clé est vide, récupérez l'intégralité de l'objet cache

  • le type de clé est string et value===undefined correspond à obtenir la valeur spécifiée

  • Les autres appels sont set, différenciez-les au sein de 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;
    }

utilisez remove pour supprimer les attributs de l'objet de cache Lors de l'appel, vous pouvez transmettre une chaîne représentant le nom de clé à supprimer, ou transmettre un tableau de chaînes contenant plusieurs noms de clés. Les noms de clés doivent également être convertis en chameau. Si aucun paramètre n’est transmis ni entrant, l’objet de données mis en cache sur le propriétaire sera directement supprimé.

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 ];
            }
        }
    }

Déterminez s'il existe des données en cache sur le propriétaire.

Data.prototype.hasData

    hasData: function( owner ) {
        var cache = owner[ this.expando ];
        return cache !== undefined && !jQuery.isEmptyObject( cache );
    }

Définition de la méthode jQuery

Après avoir défini la classe interne data, développez-la dans /src/data.js. Ajout de hasData, data, removeData, _data, _removeData et d'autres méthodes à jQuery, et ajout des méthodes data et removeData à jQuery.fn.

Les méthodes étendues dans jQuery sont toutes des encapsulations de la méthode Data Lors de l'appel de $.data(), il n'y a pas de distinction entre les opérations set et get Set et get sont distinguées à l'intérieur de Data.prototype.access . Dans le code source ci-dessous, dataUser et dataPriv sont des instances de Data, qui mettent respectivement en cache les données et indiquent si l'objet jq ajoute l'attribut data de l'élément à dataUser

<🎜. > dans
// $.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 );
    }
} );
Les seules méthodes d'expansion sont

et jQuery.fn. Au sein de data, gérez d'abord les deux situations d'appel removeData et data. Si c'est le premier cas, l'objet de données mis en cache sur $().data() est renvoyé S'il est appelé pour la première fois comme $().data({k:v}), l'attribut data sur l'élément sera également ajouté à this[0] et au $().data(). . S'il s'agit de la méthode appelante de dataUser, l'objet jq est parcouru et les données du cache sont mises à jour pour chaque nœud. D'autres méthodes d'appel telles que dataPriv et $().data({k:v}) appellent $().data(k) pour le traitement. Le $().data(k,v) ici n'est pas access. accessData.prototype.access

parcourt l'objet jq et supprime les données mises en cache sur chaque nœud.

removeData

Parmi eux,
// $().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&#39;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 );
        } );
    }
} );
est utilisé pour taper convertir l'attribut de données sur l'élément, et

est utilisé pour obtenir l'attribut de données enregistré sur le nœud de l'élément et mettre à jour getData à la en même temps. A noter que lors d'un appel en mode dataAttr, si l'attribut est introuvable sur les données mises en cache, dataUser sera appelé pour retrouver l'attribut sur l'élément. $().data(k, v)dataAttr

Articles connexes recommandés :
// 属性值是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;
}

Introduction à deux méthodes de validation de forme angulaire

Comment utiliser les fonctions JavaScript ? Introduction aux propriétés et méthodes des fonctions JavaScript

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn