1. 程式人生 > >阻止datagrid填充已經獲取到的遠端資料

阻止datagrid填充已經獲取到的遠端資料

時光流逝,彈指揮間,不經意的一年又如路上一個動人的靚影悄然消失在視線裡。我們往往都是先問自己,我們收穫了什麼,然後才想到我們付出了什麼,很少有人先問自己這一年付出了什麼,然後再去看所得。話不多說了,祝靠著搜尋引擎來到此地的同仁們,在2013年能夠大付出,然後大收入。

當datagrid設定了url屬性,表格就會通過ajax向設定的url請求資料,然後把請求的資料放到已經渲染好的表格容器中,整個過程我們可以這樣簡單地表示:

datagrid元件url方式載入資料流程圖

上圖的幾點說明:

  • onBeforeLoad事件發生在ajax請求之前的,這個事件函式如果返回false的話,將直接結束,不會請求資料。
  • onLoadError事件是當ajax請求出現故障時觸發,開發者可以在此事件中自定義提示資訊等。
  • onBeforeRender事件是view屬性的,該事件發生在把ajax請求到的資料填充到表格內容中之前。
  • 紅色部分的rend資料行,就是把ajax請求到的資料填充到表格內容裡,這個操作是呼叫view的render方法實現的。
  • onAfterRender事件也是view物件的事件,該事件在資料填充到表格之後觸發。
  • view物件是全域性性的,就是說當前頁面,所有datagrid物件公用這個view,這是由閉包與面向物件特性決定的,我們來看datagrid的魚原始碼:
    /**
     * 自動執行的匿名函式
     * @param {Object} _1b6
     * @param {Object} _1b7
     * @param {Object} _1b8
     */
    (function($){ 
    	//view為匿名函式的內部變數,其指向一個物件。
        var view = {
            render: function(_1b6, _1b7, _1b8){
                //...
            },
            renderFooter: function(_1bf, _1c0, _1c1){
                //...
            },
            renderRow: function(_1c4, _1c5, _1c6, _1c7, _1c8){
                //...
            },
            refreshRow: function(_1ce, _1cf){
                //...
            },
            updateRow: function(_1d0, _1d1, row){
                //...
            },
            insertRow: function(_1d7, _1d8, row){
                //...
            },
            deleteRow: function(_1e2, _1e3){
                //...
            },
            onBeforeRender: function(_1e8, rows){
    			//user defined
            },
            onAfterRender: function(_1e9){
                //...
            }
        };
    	//將匿名函式的內部變數賦給$.fn.datagrid.defaults全域性物件
    	//這樣就構成了閉包,匿名函式內的view變數在匿名函式的執行結束後繼續存在於記憶體中。
        $.fn.datagrid.defaults = $.extend({}, $.fn.panel.defaults, {
            //...
            view: view
    		//...
        });
    })(jQuery);
    

    所以,如果我們更改某個表格的view.onBeforeRender屬性的話,其實就是對全域性物件的更改,除非我們直接覆蓋某個表格的view指向,這樣就不會影響其它表格的view了:

    $('#tt').datagrid('options').view.onBeforeRender = function(jq,rows){};//這樣就改變了全域性變數,對別的grid也會造成影響
    $('#tt').datagrid('options').view = {onBeforeRender :function(jq,rows){},...};//這樣只改變了tt表格的view,對別的grid不會造成影響
    
  • onLoadSuccess事件發生最後,這時候資料已經填充到表格,木已成舟,已無回天之力,除非重新砍木頭。
  • 在資料填充到表格後,datagrid還有一件事要做,那就是重新整理分頁工具欄的總記錄數值。

我們可以看到,整個過程中,我們唯一有機會阻止ajax載入到的資料填充到表格的地方就是onBeforeRender事件,只要在這個事件裡面,我們將資料設定為空,不過也就沒有內容可以填充了;

我們可以直接覆寫某個表格的view,不過程式碼量太大,所以更改全域性的view物件的onBeforeRender事件更為簡潔,因view物件是公用的,你更改的話,那麼在當前頁面,所有表格的view就都跟著改了,所以在view的onBeforeRender最好是通過入參的id標識用以標識哪些表格需要阻止特定資料填充到內容區,所以,我們在頁面文件裝載完做以下定義:

$(function() {
			$.fn.datagrid.defaults.view.onBeforeRender = function(ele, rows) {
				if (ele.id == 'test') {// 只處理id為test的表格
					if (rows.length && rows[0].key == -1) {// 這地方我們假設回臺返回的資料key為-1的話,則代表此次請求的資料均為錯誤提示資訊,不與展示。
						$(ele).data('datagrid').data = {
							total : 0,
							rows : []
						};
						alert(rows[0].error);// 用彈出視窗方式通知使用者獲取資料出錯。
					}
				}
			}
		});

到這裡,我們只剩下一個問題了,那就是分頁欄還是顯示有一條或多條資料,而根據程式碼的流程圖我看可以看出分頁欄的重新整理是放在最後的,是不是就沒轍了呢?別擔心,我們有setTimeout這個法寶,在onLoadSuccess事件裡面我們延時重新整理一下分頁欄就行了:

onLoadSuccess:function(data){
				setTimeout(function(){
					var page = $('#test').datagrid("getPager");
					page.pagination('refresh',{total:0});
				},100);	
}

是不是有的童鞋要喊了:“既然分頁條能延時重新整理,那表格的內容也可以延時清空啊。”,不錯表格內容是可以通過延時的方式來清空,但是這個過程使用者的眼睛一直盯著表格內容,其展示和被清空的過程被使用者看得一清二楚。而分頁欄是死角,沒人會在意,這就是區別。

到這裡,我們也就算是完美地完成我們想要的效果了,善於思考的同學肯定會問,為什麼要用這麼彆扭的方式,後臺報錯就直接不要返回什麼資料,都放在onLoadError事件裡提示不就得了。

事實上大多人也將異常放在onLoadError中處理的,只有少數情況才會對後臺返回的資料有特殊要求,此文更重要的目的是講述datagrid元件url方式載入和填充資料的過程。

  ******轉載:http://www.easyui.info/archives/839.html