jQuery數據緩存data(name, value)詳解及實現

    做爲一名程序員,一提到「緩存」你很容易聯想到「客戶端(瀏覽器緩存)」和「服務器緩存」。客戶端緩存是存在瀏覽者電腦硬盤上的,即瀏覽器臨時文件夾,而服務器緩存是存在服務器內存中,固然在一些高級應用場合也有專門的緩存服務器,甚至有利用數據庫進行緩存的實現。固然這些都不在本文的討論範圍,本文要討論的是最流行的JavaScript框架jQuery的數據緩存實現原理,這是jQuery1.2.3版開始加入的新功能。 javascript

1、 jQuery數據緩存的做用 html

jQuery數據緩存的做用在中文API中是這樣描述的:「用於在一個元素上存取數據而避免了循環引用的風險」。如何理解這句話呢,看看我下面的舉例,不知道合不合適,若是你有更好的例子能夠告訴我。
(1) 存在循環引用風險的例子(注意getDataByName(name)方法中的for in語句):
java

<a href="javascript:void(0);" onclick="showInfoByName(this.innerHTML);">Tom</a>
<a href="javascript:void(0);" onclick="showInfoByName(this.innerHTML);">Mike</a>
<script type="text/javascript">

     var userInfo = [
        {
            "name": "Tom",
            "age": 21,
            "phone": "020-12345678"
        }, 
        {
             "name": "Mike",
             "age": 23,
             "phone": "020-87654321"
        }];

     function getDataByName(name) {
        for (var i in userInfo){
            if (userInfo[i].name == name){
                 return userInfo[i];
                 break;
             }
        }

     }

     function showInfoByName(name){
         var info = getDataByName(name);
         alert('name:' + info.name + '\n' + 'age:' + info.age + '\n' + 'phone:' + info.phone);
     }
</script>

(2) 優化循環引用風險的例子(本例子其實與jQuery緩存實現原理差很少了,本例子重點在於改寫了userInfo這個JSON結構,使name與對象key直接對應): node


<a href="javascript:void(0);" onclick="showInfoByName(this.innerHTML);">Tom</a><br/><a href="javascript:void(0);" onclick="showInfoByName(this.innerHTML);">Mike</a>
<script type="text/javascript">
    var userInfo = 
    {
         "Tom": 
             {
                 "name": "Tom",
                 "age": 21,
                 "phone": "020-12345678"
             },
         "Mike": 
             {
                 "name": "Mike",
                 "age": 23,
                 "phone": "020-87654321"
            }
      };

     function showInfoByName(name){
        var info = userInfo[name];
        alert('name:' + info.name + '\n' + 'age:' + info.age + '\n' + 'phone:' + info.phone);
     }

</script>


2、簡單實現jQuery設置數據緩存方法


jQuery數據緩存的實現實際上是很簡單的,下面我來實現jQuery設置數據緩存方法,我讓代碼儘可能的簡單,這有助於你更容易瞭解data的實現原理。函數與測試代碼以下: 程序員

<div id="div1"> div1</div>
<div id="div2">div2
</div>
<script type="text/javascript">
    //cache對象結構像這樣{"uuid1":{"name1":value1,"name2":value2},"uuid2":{"name1":value1,"name2":value2}}
    //每一個uuid對應一個elem緩存數據,每一個緩存對象是能夠由多個name/value對組成的,而value是能夠是任何數據類型的
    //好比能夠像這樣在elem下存一個JSON片斷:$(elem).data('JSON':{"name":"Tom","age":23})
    var cache = {};

    //expando做爲elem一個新加屬性,爲了防止與用戶本身定義的產生衝突,這裏採用可變後綴
    var expando = 'jQuery' + new Date().getTime();

     var uuid = 0;

    function data(elem, name, data){

        //至少保證要有elem和name兩個參數才能進行取緩存或設置緩存操做
        if (elem && name){
            //嘗試取elem標籤expando屬性
            var id = elem[expando];
            if (data){
                //設置緩存數據
                if (!id)
                id = elem[expando] = ++uuid;
                //若是cache中id鍵對象不存在(即這個elem沒有設置過數據緩存),先建立一個空對象
                if (!cache[id]) cache[id] = {};
                cache[id][name] = data;
            } else{
                //獲取緩存數據
                if (!id)
                return 'Not set cache!';
                else
                return cache[id][name];
            }
        }
    }


    var div = document.getElementById('div1');
    data(div, "tagName", "div");
    data(div, "ID", "div1");
    alert(data(div, "tagName")); //div
    alert(data(div, "ID")); //div1
    var div2 = document.getElementById('div2');
    alert(data(div2, "tagName")); //Not set cache!
    < /script>

3、使用jQuery數據緩存注意事項 web

    1.由於jQuery緩存對象是全局的,在AJAX應用中,因爲頁面刷新不多,這個對象將一直存在,隨着你對data的不斷操做,頗有可能由於使用不當,使得這個對象不斷變大,最終影響程序性能。因此咱們要及時清理這個對象,jQuery也提供了相應方法:removeData(name),name就是你當初設置data值時使用的name參數。 數據庫


         另外,根據我對jQuery代碼的瞭解,發現下面幾種狀況不須要手動清除數據緩存:

  •  對elem執行remove()操做,jQuery會清除對象可能存在的緩存。jQuery相關源代碼參考:


remove: function(selector) {
    if (!selector || jQuery.filter(selector, [this]).length) {
        // Prevent memory leaks
        jQuery("*", this).add([this]).each(function() {
            jQuery.event.remove(this);
            jQuery.removeData(this);
        });
        if (this.parentNode) this.parentNode.removeChild(this);
    }
}
  •  對elem執行empty()操做,若是當前elem子元素存在數據緩存,jQuery也會清除子對象可能存在的數據緩存,由於jQuery的empty()實現實際上是循環調用remove()刪除子元素。jQuery相關源代碼參考:
empty: function() {
    // Remove element nodes and prevent memory leaks
    jQuery(this).children().remove();
    // Remove any remaining nodes
    while (this.firstChild) this.removeChild(this.firstChild);
}
    2 .   jQuery複製節點clone()方法不會複製data緩存,準確說jQuery不會在全局緩存對象中分配一個新節點存放新複製elem緩存。jQuery在clone()中把可能存在的緩存指向屬性(elem的expando屬性)替換成空。若是直接把這個屬性複製,就會致使原先和新複製的elem都指向一個數據緩存,中間的互操做都將會影響到兩個elem的緩存變量。如下jQuery代碼就是把expando屬性刪除(jQuery1.3.2,較早版本不是這樣處理,顯然新版本的這個方法性能更好)。
jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0];
把數據緩存一塊兒複製有時候也是頗有用的,好比在拖動操做中,咱們點擊源目標elem節點就會複製出一個半透明的elem副本開始拖動,並把data緩存複製到拖動層中,等到拖動結束,咱們就可能取到當前拖動的elem相關信息。如今jQuery方法沒有給咱們提供這樣的處理,怎麼辦法。第一個辦法是改寫jQuery代碼,這個方法顯然很傻,很不科學。正確作法是複製源目標的data,把這些data都從新設置到複製出來的elem中,這樣在執行data(name, value)方法時,jQuery會在全局緩存對象中爲咱們開闢新空間。實現代碼以下:
if (typeof($.data(currentElement)) == 'number') {
    var elemData = $.cache[$.data(currentElement)];
    for (var k in elemData) {
        dragingDiv.data(k, elemData[k]);
    }
}
在上面代碼中,$.data(elem,name,data)包含三個參數,若是隻有一個elem參數,這個方法返回它的緩存key(即uuid),利用這個key就能夠獲得整個緩存對象,而後把對象的數據都複製到新的對象。

做者:WebFlash
出處:http://webflash.cnblogs.com 
本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利。 瀏覽器

相關文章
相關標籤/搜索