搜尋
首頁web前端js教程jQuery中data操作的方法及jQuery的定義

jQuery中data操作的方法及jQuery的定義

Aug 04, 2018 pm 04:36 PM
javascriptjquery

這篇文章要跟大家介紹的內容是關於jQuery中data操作的方法及jQuery的定義,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

jQuery中有兩個關於data操作的方法

$().data()

$.data(elem);

內部其實作都離不開自訂類別Data

內部類別Data

Datasrc/data/Data.js定義,建置時為實例新增expando屬性,作為唯一標識

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

在原型上新增了多個方法

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

在jq內部,使用cache方法取得快取的資料。傳入一個參數owner,表示要取得快取資料的物件。判斷在owner上是否有expando屬性,如果沒有,說明這個owner是否第一次調用,需要在其初始化快取資料物件。判斷節點的類型,如果是元素節點或document節點或物件時,可以設定快取資料。如果是元素節點或是document節點,直接使用物件字面量來賦值,屬性名稱是expando,值為空物件。如果是物件的話,使用Object.defineProperty為其定義數據,屬性名稱也是expando,初始化為{},同時屬性描述符可以更改,不可列舉。

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

使用set來更新快取對象,分為data(key,value)data(obj)兩種呼叫情況,儲存時要將鍵名儲存為駝峰命名法。

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

使用get來取得快取對象,呼叫時有data(key)data()。未指定key時直接傳回整個cache對象,否則傳回cache[key]。鍵名也要轉為駝峰命名。

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

對呼叫的方式區分,內部呼叫setget

透過參數的數量和型別區分:

  • key為空時,取得整個cache物件

  • key型別為stringvalue===undefined 對應取得指定值

  • 其他呼叫皆為set,在 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;
    }

使用remove來刪除快取物件屬性,當呼叫時,可以傳入一個string,表示要刪除的鍵名,或是傳入一個保存多個鍵名的string數組。鍵名也要轉為駝峰命名。如果不傳入出參數,則直接刪除掉在owner上的快取資料物件。

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 <p>判斷owner上是否有快取資料。 </p><h3 id="code-Data-prototype-hasData-code"><code>Data.prototype.hasData</code></h3><pre class="brush:php;toolbar:false">    hasData: function( owner ) {
        var cache = owner[ this.expando ];
        return cache !== undefined && !jQuery.isEmptyObject( cache );
    }

#jQuery方法的定義

##定義後內部類別

data #後,在/src/data.js進行拓展。在jQuery新增了hasDatadataremoveData_data_removeData等方法,在jQuery.fn上新增了dataremoveData方法。

在jQuery拓展的方法,都是Data方法的封裝,在呼叫時

$.data()時,並無對set#和 get操作區分,在Data.prototype.access內部區分set和get。在下方原始碼中,dataUserdataPrivData#實例,分別為快取資料和表示jq物件是否將元素的data屬性加入dataUser

// $.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 );
    }
} );

jQuery.fn#上拓展的方法只有dataremoveData。在data內,先將$().data()$().data({k:v})兩個呼叫情況進行處理。如果是第一種情況,則傳回在this[0]上的快取資料對象,如果是第一次以$().data()的方式調用,同時也會將元素上的data屬性加入dataUser中,並更新dataPriv。如果是$().data({k:v})的呼叫方式,則遍歷jq對象,為每個節點更新快取資料。其他呼叫方式如$().data(k)$().data(k,v)則呼叫access進行處理。此處的access並非Data.prototype.access

removeData則遍歷jq對象,刪除在每個節點上的快取資料。

// $().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 );
        } );
    }
} );
其中,

getData用於對元素上的data屬性進行類型轉換,dataAttr用於取得保存在元素節點上的data屬性,並同時更新dataUser。要注意的是,以$().data(k, v)方式呼叫時,如果在快取資料上查找不到屬性,則會呼叫dataAttr在元素中尋找屬性。

// 属性值是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;
}
相關文章推薦:

Angular表單驗證的兩種方法介紹

JavaScript函數怎麼用?JavaScript函數的屬性和方法的介紹

#

以上是jQuery中data操作的方法及jQuery的定義的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
超越瀏覽器:現實世界中的JavaScript超越瀏覽器:現實世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

使用Next.js(後端集成)構建多租戶SaaS應用程序使用Next.js(後端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

如何使用Next.js(前端集成)構建多租戶SaaS應用程序如何使用Next.js(前端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

JavaScript:探索網絡語言的多功能性JavaScript:探索網絡語言的多功能性Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

JavaScript的演變:當前的趨勢和未來前景JavaScript的演變:當前的趨勢和未來前景Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

神秘的JavaScript:它的作用以及為什麼重要神秘的JavaScript:它的作用以及為什麼重要Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

Python還是JavaScript更好?Python還是JavaScript更好?Apr 06, 2025 am 12:14 AM

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。1.Python以简洁语法和丰富库生态著称,适用于数据分析和Web开发。2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。

如何安裝JavaScript?如何安裝JavaScript?Apr 05, 2025 am 12:16 AM

JavaScript不需要安裝,因為它已內置於現代瀏覽器中。你只需文本編輯器和瀏覽器即可開始使用。 1)在瀏覽器環境中,通過標籤嵌入HTML文件中運行。 2)在Node.js環境中,下載並安裝Node.js後,通過命令行運行JavaScript文件。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境