EXT Grid控件精華展現 javascript

 

無論是界面之美,還是功能之強,ext的表格控件都高居榜首。

單選行,多選行,高亮顯示選中的行,推拽改變列寬度,按列排序,這些基本功能咱們就不提了。

自動生成行號,支持checkbox全選,動態選擇顯示哪些列,支持本地以及遠程分頁,可以對單元格按照自己的想法進行渲染,這些也算可以想到的功能。

再加上可編輯grid,添加新行,刪除一或多行,提示髒數據,推拽改變grid大小,grid之間推拽一或多行,甚至可以在tree和grid之間進行拖拽,啊,這些功能實在太神奇了。更令人驚歎的是,這些功能竟然都在ext表格控件裏實現了。

呵呵~不過ext也不是萬能的,與fins的ecside比較,ext不能鎖定列(土豆說1.x裏支持鎖定列,但是2.0裏沒有了,因爲影響效 率。),也沒有默認的統計功能,也不支持excel,pdf等導出數據。另外fins說,通過測試ecside的效率明顯優於ext呢。:)

2.2. 讓我們搞一個grid出來耍耍吧。

光說不練不是我們的傳統,讓我們基於examples裏的例子,來自己搞一個grid看看效果,同時也可以知道一個grid到底需要配置些什麼東西。

  1. 首先我們知道表格肯定是二維的,橫着叫行,豎着叫列。跟設計數據庫,新建表一樣,我們要先設置這個表有幾列,每列叫啥名字,啥類型,咋顯示,這個表格的骨架也就出來了。

    ext裏,這個列的定義,叫做ColumnModel,簡稱cm的就是它,它作爲整個表格的列模型,是要首先建立起來的。

    這裏我們建立一個三列的表格,第一列叫編號(code),第二列叫名稱(name),第三列叫描述(descn)。

    var cm = new Ext.grid.ColumnModel([
        {header:'編號',dataIndex:'id'},
        {header:'名稱',dataIndex:'name'},
        {header:'描述',dataIndex:'descn'}
    ]);

    看到了吧?非常簡單的定義了三列,每列的header表示這列的名稱,dataIndex是跟後面的東西對應的,咱們暫且不提。現在只要知道有了三列就可以了。

  2. 有了表格的骨架,現在我們要向裏邊添加數據了。這個數據當然也是二維了,爲了簡便,我們學習examples裏的array-grid.js裏的方式,把數據直接寫到js裏。

    var data = [
        ['1','name1','descn1'],
        ['2','name2','descn2'],
        ['3','name3','descn3'],
        ['4','name4','descn4'],
        ['5','name5','descn5']
    ];

    很顯然,我們這裏定義了一個二維數據, (什麼?你不知道這是二維數組?快改行吧,這裏不是你該待的地方。)

    這個有五條記錄的二維數組,顯示到grid裏就應該是五行,每行三列,正好對應這id,name,descn,在我們的腦子裏應該可以想像出grid顯示的結果了,爲了讓想像變成顯示,我們還需要對原始數據做一下轉化。

  3. 因 爲咱們希望grid不只能支持array,還可以支持json,支持xml,甚至支持咱們自己定義的數據格式,ext爲咱們提供了一個橋 樑,Ext.data.Store,通過它我們可以把任何格式的數據轉化成grid可以使用的形式,這樣就不需要爲每種數據格式寫一個grid的實現了。 現在咱們就來看看這個Ext.data.Store是如何轉換array的。

    var ds = new Ext.data.Store({
        proxy: new Ext.data.MemoryProxy(data),
        reader: new Ext.data.ArrayReader({}, [
            {name: 'id'},
            {name: 'name'},
            {name: 'descn'}
        ])
    });
    ds.load();

    ds要對應兩個部分:proxy和reader。proxy告訴我們從哪裏獲得數據,reader告訴我們如何解析這個數據。

    現在我們用的是Ext.data.MemoryProxy,它是專門用來解析js變量的。你可以看到,我們直接把data作爲參數傳遞進去了。

    Ext.data.ArrayReader 專門用來解析數組,並且告訴我們它會按照定義的規範進行解析,每行讀取三個數據,第一個叫id,第二個叫name,第三個descn。是不是有些眼熟,翻 到前面cm定義的地方,哦,原來跟dataIndex是對應的。這樣cm就知道哪列應該顯示那條數據了。唉,你要是能看明白這一點,那你實在是太聰明瞭。

    記得要執行一次ds.load(),對數據進行初始化。

    有兄弟可能要問了,要是我第一列數據不是id而是name,第二列數據不是name而是id咋辦?嗯,嗯,這個使用就用mapping來解決。改改變成這樣:

    var ds = new Ext.data.Store({
        proxy: new Ext.data.MemoryProxy(data),
        reader: new Ext.data.ArrayReader({}, [
            {name: 'id', mapping: 1},
            {name: 'name', mapping: 0},
            {name: 'descn', mapping: 2}
        ])
    });

    這樣如截圖所見,id和name兩列的數據翻轉了。如此這般,無論數據排列順序如何,我們都可以使用mapping來控制對應關係,唯一需要注意的是,索引是從0開始的,所以對應第一列要寫成mapping:0,以此類推。

  4. 哈哈,萬事俱備只欠東風,表格的列模型定義好了,原始數據和數據的轉換都做好了,剩下的只需要裝配在一起,我們的grid就出來了。

    var grid = new Ext.grid.Grid('grid', {
        ds: ds,
        cm: cm
    });
    grid.render();

    注意:上頭是ext-1.x的寫法,Ext.grid.Grid的第一個參數是渲染的id,對應在html裏應該有一個 <div id="grid"></div>的東西,這樣grid才知道要把自己畫到哪裏。

    創建完grid以後,還要用grid.render()方法,讓grid開始渲染,這樣才能顯示出來。

  5. 好了,把所有代碼組合到一起,看看效果吧。

    var cm = new Ext.grid.ColumnModel([
            {header:'編號',dataIndex:'id'},
            {header:'名稱',dataIndex:'name'},
            {header:'描述',dataIndex:'descn'}
        ]);
    
        var data = [
            ['1','name1','descn1'],
            ['2','name2','descn2'],
            ['3','name3','descn3'],
            ['4','name4','descn4'],
            ['5','name5','descn5']
        ];
    
        var ds = new Ext.data.Store({
            proxy: new Ext.data.MemoryProxy(data),
            reader: new Ext.data.ArrayReader({}, [
                {name: 'id'},
                {name: 'name'},
                {name: 'descn'}
            ])
        });
        ds.load();
    
        var grid = new Ext.grid.Grid('grid', {
            ds: ds,
            cm: cm
        });
        grid.render();

    看看吧,這就是咱們搞出來的grid了。

html例子是lingo-sample/1.1.1目錄下的02-01.html,把這個目錄copy到ext-1.x的example目錄下,就可以直接打開觀看效果。

2.3. 上邊那個是1.x的,2.0稍微有些不同哦

首先,Ext.grid.Grid已經不見了,咱們需要用Ext.grid.GridPanel。需要傳遞的參數也有少許區別。

var grid = new Ext.grid.GridPanel({
    el: 'grid',
    ds: ds,
    cm: cm
});

看到了嗎?負責指定渲染位置的id放到了{}裏邊,對應的名字是el。似乎ext2裏對這些參數進行了統一,比以前更整齊了。

因爲其他地方都一樣,我就不多說了,html例子在是lingo-sample/2.0目錄下的02-01.html。

從截圖上看,少了斑馬條,下邊多了一條線,應該只是css有所不同吧。

默認情況下,兩個版本的grid都可以拖拽列,也可以改變列的寬度。不知道怎麼禁用這兩個功能呢。

最大的不同應該是1.x裏默認支持的右鍵效果,在2.0裏不見了。

按shift和ctrl多選行的功能倒是都有。區別是,全選後,1.x必須按住ctrl才能取消,直接單擊其中一個行,不會取消全選功能,而2.0裏只需要任意點擊一行,就取消全選,只選中剛纔點擊的那行。

哦,哦,那顏色不要也算是區別吧。

2.4. 按順序,咱們先要把常見功能講到,讓grid支持按列排序

其實很簡單,需要小小改動一下列模型。

var cm = new Ext.grid.ColumnModel([
    {header:'編號',dataIndex:'id',sortable:true},
    {header:'名稱',dataIndex:'name'},
    {header:'描述',dataIndex:'descn'}
]);

如果你英語還可以,或者懂得查字典的話(軟件翻譯也算),那麼你就會知道,多出來的這個sortable屬性應該是可以排序的意思。現在咱們試一下改動後的效果。

看到了沒有?編號的標題上有個小小的箭頭,表格裏的數據也是按照編號做的逆序排列,如此簡單,我們就實現了按列排序。

很有趣的是,2.0加上sortable以後,1.x那種右鍵功能也跑回來了,不過它用的不是右鍵,而是下拉菜單似的實現方式。

什麼?你問爲什麼其他兩列無法排序?!嗯,好像是因爲你還沒有給另兩列添加sortable屬性。

怎麼加?!按編號那樣加就行了。

還是不會?!-_-。

var cm = new Ext.grid.ColumnModel([
    {header:'編號',dataIndex:'id',sortable:true},
    {header:'名稱',dataIndex:'name',sortable:true},
    {header:'描述',dataIndex:'descn',sortable:true}
]);

這樣所有列都可以排序了。什麼?怎麼取消排序?!-_-。

2.5. 讓單元格里顯示紅色的字,圖片,按鈕,你還能想到什麼?

嘿,希望你跟我一樣,不願意只能在grid裏看到文字,至少不是單調的,毫無特色的文字。有些人就問了,如果我想改變一下單元格里顯示內容,應該怎麼辦呢?

非常不幸的是,ext的作者,偉大的jack早已經想到了,說真的,你沒想到的,他都想到了,不只想到了,他還做出來了。

唉,這就是區別啊。爲啥你就不能動手做些東西呢?就知道向別人要這要那,唉。

首先,我宣佈,偶們的數據要擴充啦,每個人要加上一個性別字段。

var data = [
    ['1','male','name1','descn1'],
    ['2','female','name2','descn2'],
    ['3','male','name3','descn3'],
    ['4','female','name4','descn4'],
    ['5','male','name5','descn5']
];

男女搭配,幹活不累撒。而且現在中國就是男多女少,我就還沒對象呢。徵婚中,單身女性加(QQ)771490531詳談。

你可以試試不改其他的部分,顯示的結果是不會改變的,因爲原始數據要經過ds的處理才能被grid使用,那麼下一步我們就開始修改ds,把性別加進去。

var ds = new Ext.data.Store({
    proxy: new Ext.data.MemoryProxy(data),
    reader: new Ext.data.ArrayReader({}, [
        {name: 'id'},
        {name: 'sex'},
        {name: 'name'},
        {name: 'descn'}
    ])
});

添加了一行{name: 'sex'},把數組的第二列映射爲性別。現在grid可以感覺到sex了,嘿嘿。

不過grid還顯示不了性別這列,因爲咱們還沒改cm。

var cm = new Ext.grid.ColumnModel([
    {header:'編號',dataIndex:'id'},
    {header:'性別',dataIndex:'sex'},
    {header:'名稱',dataIndex:'name'},
    {header:'描述',dataIndex:'descn'}
]);

到現在其實都沒什麼新東西,但是你不覺得光看平板字,很難分出哪個是GG哪個是MM嗎?聽說過紅男綠女沒?要是男的都加上紅色,女的都變成綠色,那不是清楚多了。就像下面一樣。

怎麼樣?是不是效果大不同了。你不會認爲很難吧,嗯,確實,如果你對html和css完全搞不明白的話,勸你還是先去學學吧,對自己有信心的往下看。

var cm = new Ext.grid.ColumnModel([
    {header:'編號',dataIndex:'id'},
    {header:'性別',dataIndex:'sex',renderer:function(value){
            if (value == 'male') {
                return "<span style='color:red;font-weight:bold;'>紅男</span>";
            } else {
                return "<span style='color:green;font-weight:bold;'>綠女</span>";
            }
        }},
    {header:'名稱',dataIndex:'name'},
    {header:'描述',dataIndex:'descn'}
]);

別被嚇到,這麼一大段其實就是判斷是男是女,然後配上顏色。你要是覺得亂,也可以這麼做。

function renderSex(value) {
    if (value == 'male') {
        return "<span style='color:red;font-weight:bold;'>紅男</span>";
    } else {
        return "<span style='color:green;font-weight:bold;'>綠女</span>";
    }
}
var cm = new Ext.grid.ColumnModel([
    {header:'編號',dataIndex:'id'},
    {header:'性別',dataIndex:'sex',renderer:renderSex},
    {header:'名稱',dataIndex:'name'},
    {header:'描述',dataIndex:'descn'}
]);

實際上這個renderer屬性至關重要,它的值是一個function,哦,你說不知道js裏function可以這麼用?那麼恭喜你,現在你知道了。

renderer會傳遞個參數進去,咱們grid裏看到的,是這個函數的返回值,怎麼樣,神奇吧?

同志們,你們也應該看到了,返回html就可以,是html啊,html裏有的東西,你返回什麼就顯示什麼,顏色,鏈接,圖片,按鈕,只要你願意,整個網頁都可以返回回去。還有什麼做不到的?哦,你不會html,那沒轍,回去學吧。

咱們先來個圖片。

function renderSex(value) {
    if (value == 'male') {
        return "<span style='color:red;font-weight:bold;'>紅男</span><img src='user_male.png' />";
    } else {
        return "<span style='color:green;font-weight:bold;'>綠女</span><img src='user_female.png' />";
    }
}

是不是太簡單了,下面咱們來玩點兒高級的。

function renderDescn(value, cellmeta, record, rowIndex, columnIndex, store) {
    var str = "<input type='button' value='查看詳細信息' οnclick='alert(\"" +
        "這個單元格的值是:" + value + "\\n" +
        "這個單元格的配置是:{cellId:" + cellmeta.cellId + ",id:" + cellmeta.id + ",css:" + cellmeta.css + "}\\n" +
        "這個單元格對應行的record是:" + record + ",一行的數據都在裏邊\\n" +
        "這是第" + rowIndex + "行\\n" +
        "這是第" + columnIndex + "列\\n" +
        "這個表格對應的Ext.data.Store在這裏:" + store + ",隨便用吧。" +
        "\")'>";
    return str;
}

來看看我們可以在render裏用到多少參數:

  1. value是當前單元格的值

  2. cellmeta裏保存的是cellId單元格id,id不知道是幹啥的,似乎是列號,css是這個單元格的css樣式。

  3. record是這行的所有數據,你想要什麼,record.data["id"]這樣就獲得了。

  4. rowIndex是行號,不是從頭往下數的意思,而是計算了分頁以後的結果。

  5. columnIndex列號太簡單了。

  6. store,這個厲害,實際上這個是你構造表格時候傳遞的ds,也就是說表格裏所有的數據,你都可以隨便調用,唉,太厲害了。

有個同學就問啦:EXT render的參數,是如何得到的呢。因爲你講的那些都是EXT自己內部的。它是如何把這些參數傳遞給render的呢?

這個問題其實比較簡單,只是你們想複雜了。既然是函數,就肯定有調用它的地方,你找到GridView.js在裏邊搜索一下renderer,就會看到調用render的地方,這些參數都是在這裏傳進去的。

好,看看效果吧。

剩下的,就是發揮各位聰明才智的時候了,舞臺已經搭好,看你如何表演了。

html例子,1.x版本在lingo-sample/1.1.1目錄下的02-02.html,2.0的版本在lingo-sample/2.0目錄下的02-02.html。

2.6. 更進一步,自動行號和多選checkbox

實際上行號和多選checkbox都是renderer的延伸,當然多選checkbox更酷一點兒,兩者經常一起使用,所以讓我們放在一起討論好了。

2.6.1. 自動行號

只需要在cm中加上一行,這一行不會與ds中的任何數據對應,這也告訴我們可以憑空製作列,哈哈。

在之前的例子上改啦。

var cm = new Ext.grid.ColumnModel([
    {header:'NO.',renderer:function(value, cellmeta, record, rowIndex){
        return rowIndex + 1;
    }},
    {header:'編號',dataIndex:'id'},
    {header:'性別',dataIndex:'sex'},
    {header:'名稱',dataIndex:'name'},
    {header:'描述',dataIndex:'descn'}
]);

如吾等所願,不指定dataIndex,而是直接根據renderer返回rowIndex + 1,因爲它是從0開始的,所以加個一。截圖如下。

1.x的例子在lingo-sample/1.1.1/02-03.html

很遺憾的是,2.0裏有自己的默認實現了,咱們不能展現自己的手工技藝了,還是乖乖使用jack提供的東東吧。

於是,在2.0裏cm就變成了這幅模樣。

var cm = new Ext.grid.ColumnModel([
    new Ext.grid.RowNumberer(),
    {header:'編號',dataIndex:'id'},
    {header:'性別',dataIndex:'sex'},
    {header:'名稱',dataIndex:'name'},
    {header:'描述',dataIndex:'descn'}
]);

你絕對會同意我的意見,Jack's work is amazing.實在是太神奇了。看看截圖就知道。

2.0的例子在lingo-sample/2.0/02-03.html

2.6.2. 全選checkbox的時間了,請允許我讓2.0先上場。

因爲2.0裏有checkboxSelectionModel,這樣完全可以證實用別人的輪子,比自己造輪子要方便。而且咱們造的輪子完全沒有jack圓。不信的話,看下面1.x裏的實現。

我們一直在修改cm,這次我們也要對它動刀了,不過SelectionModel既sm也要處理一下,這是爲了改變單選和多選行的方式,以前這些可以靠shift或ctrl實現,而現在這些都要與checkbox關聯上了。

啦啦啦,先看圖片,後看代碼。

先看看具體多了什麼

var sm = new Ext.grid.CheckboxSelectionModel();

神奇的是這個sm身兼兩職,使用的時候既要放到cm裏,也要放到grid中。代碼如下。

var cm = new Ext.grid.ColumnModel([
    new Ext.grid.RowNumberer(),
    sm,
    {header:'編號',dataIndex:'id'},
    {header:'性別',dataIndex:'sex'},
    {header:'名稱',dataIndex:'name'},
    {header:'描述',dataIndex:'descn'}
]);

var grid = new Ext.grid.GridPanel({
    el: 'grid',
    ds: ds,
    cm: cm,
    sm: sm
});

然後你就可以得到效果啦,代碼在lingo-sample/2.0/02-04.html。

2.6.3. 1.x時代的全選checkbox。

理論上只需要給cm再加一列,像自動編號那樣,不對應數據,只顯示checkbox就可以了。難點就是checkbox與某一行被選擇的時候要對應上,用checkbox選擇上,sm裏也要讓這一行被選中,反之亦然。嗯,估計會比較複雜呢。

先放上顯示checkbox的代碼和截圖:

var cm = new Ext.grid.ColumnModel([
    {header:'NO.',renderer:function(value, cellmeta, record, rowIndex){
        return rowIndex + 1;
    }},
    {header:'<input type="checkbox" οnclick="selectAll(this)">',renderer:function(value, cellmeta, record, rowIndex){
        return '<input type="checkbox" name="cb">';
    }},
    {header:'編號',dataIndex:'id'},
    {header:'性別',dataIndex:'sex'},
    {header:'名稱',dataIndex:'name'},
    {header:'描述',dataIndex:'descn'}
]);

與sm對接的方面比較麻煩,好在extjs.com上已經有擴展了,或者你可以看看我們弄下來的。 看看1.x多選樹的截圖。

2.7. 分頁了嗎?分頁了嗎?如果還沒分就看這裏吧。

如果你有一千條信息,一次都輸出到grid裏,然後讓客戶用下拉條一點兒一點兒去找吧。我們這裏可是要做一個分頁效果了,不用滾動屏幕,或者滾動一下就可以看到本頁顯示的數據,如果想看其他的只需要翻頁就可以了。同志們,加強客戶體驗呀。

實際上,grid控件挺耗性能的,據土豆講一個頁面上放3個grid就可以感覺到響應變慢,以前看過介紹,grid裏顯示數據過多,聽說是上千條,也會明顯變慢。

所以說分頁是必不可少滴,而且jack提供了方便集成分頁工具條的方式,不用一下實在是太浪費了。

兩步走,讓grid集成分頁。

2.7.1. 表面工作,先把分頁工具條弄出來。

從圖片可以清晰的看到,在grid下邊多出來一行東東,包括了前一頁,後一頁,第一頁,最後一頁,刷新,以及提示信息。而我們不過寫了如下幾行代碼而已,神奇呀。

var gridFoot = grid.getView().getFooterPanel(true);

var paging = new Ext.PagingToolbar(gridFoot, ds, {
    pageSize: 10,
    displayInfo: true,
    displayMsg: '顯示第 {0} 條到 {1} 條記錄,一共 {2} 條',
    emptyMsg: '沒有記錄'
});

首先使用grid.getView().getFootPanel(true),獲得grid下邊那一條,嘿嘿,人家grid就設計的這麼好,腳底下專門留了地方讓你放東西。我們老實不客氣,把Ext.PagingToolbar放到上邊,就可以顯示分頁工具條了。

這分頁工具條可不是個擺設,你按了前一頁,後一頁,整個grid都要有反應纔對,要不咱們費勁弄這個麼東西過來幹嘛呀?所以,我們在構造 PagingToolbar的時候,不但告訴它,在gridFoot上顯示,還告訴它,進行分頁跳轉的時候,要對ds也進行操作。這個ds就是grid用 來獲取和顯示數據的,它一變整個grid都發生變化,嘿嘿~這就算共享數據模型了。厲害呀。

知道了分頁的玄機,讓我們揉揉眼睛,好好看看裏邊的參數。

  1. pageSize,是每頁顯示幾條數據。

  2. displayInfo,跟下面的配置有關,如果是false就不會顯示提示信息。

  3. displayMsg,只有在displayInfo:true的時候纔有效,用來顯示有數據的時候的提示信息,中國人應該看得懂漢語,到時候{0},{1},{2}會自動變成對應的數據,咱們只需要想辦法把話說通就行了。

  4. emptyMsg,要是沒數據就顯示這個,jack實在太貼心了,連這些小處都考慮得如此精細。

最好要注意的是,這段代碼必須放在grid.render()之後,估計是因爲動態生成grid的dom後,才能獲得對應的footPanel。

現在給出例子,1.x的例子在lingo-sample/1.1.1/02-05.html。

2.7.2. 2.0賜予我們更大的靈活性

其實,在下,一直,對於:必須先渲染grid才能獲得footPanel這事非常憤恨,你想啊,本來分頁也應該屬於初始化的一部分,現在卻要先初始化grid,配置完畢,渲染,回過頭來再從grid裏把footPanel拿出來,再咕噥分頁的配置。真,真,真鬱悶呀。

所以2.0裏的方式,簡直大快民心。

var grid = new Ext.grid.GridPanel({
    el: 'grid',
    ds: ds,
    cm: cm,
    bbar: new Ext.PagingToolbar({
        pageSize: 10,
        store: ds,
        displayInfo: true,
        displayMsg: '顯示第 {0} 條到 {1} 條記錄,一共 {2} 條',
        emptyMsg: "沒有記錄"
    })
});
ds.load();

嘿嘿,加一個bbar的參數就可以了,bbar就是bottom bar啦,底端工具條。

不過還是要注意一點,與1.x中不同的是,如果配置了分頁工具條,ds.load()就必須在構造grid以後才能執行,否則分頁工具條會不起作用。看來分頁工具條會把自己和ds做一些關聯,來完成與grid共享數據模型的。

對了,還有一點不同,1.x中分頁條不會隨着瀏覽器的大小改變,自動放縮,這點在2.0中也解決了。

2.0的例子在lingo-sample/2.0/02-05.html。

2.7.3. 迫不得已,要加上後臺腳本了。

grid會每次都顯示ds中所有的數據,咱們沒法利用靜態數據好好演示分頁,於是,必須寫後臺腳本,讓ext與後臺進行數據交互才能看到真實的分頁效果。

咱們儘量在原來的基礎上修改啊,把注意力集中在關鍵部位,一次性突破。

我不會其他語言,後臺就用jsp寫啦。有個好消息是隻要返回的數據格式一樣,ext纔不管後臺是什麼寫的呢。也就是這樣,不管你以後用什麼實現後臺,前臺的ext代碼都一樣。

<%
String start = request.getParameter("start");
String limit = request.getParameter("limit");
try {
    int index = Integer.parseInt(start);
    int pageSize = Integer.parseInt(limit);

    String json = "{totalProperty:100,root:[";
    for (int i = index; i < pageSize + index; i++) {
        json += "{id:" + i + ",name:'name" + i + "',descn:'descn" + i + "'}";
        if (i != pageSize + index - 1) {
            json += ",";
        }
    }
    json += "]}";
    response.getWriter().write(json);
} catch(Exception ex) {
}
%>

下面我們來解讀這段jsp代碼:

  1. 在進行操作之前,我們先要獲得ext傳遞過來的兩個參數:start和limit,start指的從第幾個數據開始顯示,limit是說從start開始,一共要用多少個數據,當然返回的數據可能會小於這個值。

  2. 咱們在後臺模擬對100條數據進行分頁,在獲得了start和limit之後再生成json格式的數據。

    何謂json?在理論講解之前先看看實例,讓我們能有個感性認識,至於以後能不能昇華到理性認識,就看各位的悟性了。

    模擬ext訪問後臺,並傳遞兩個參數start=0&limit=10,把獲得的數據稍微整理一下,是這個樣子。

    {totalProperty:100,root:[
        {id:0,name:'name0',descn:'descn0'},
        {id:1,name:'name1',descn:'descn1'},
        {id:2,name:'name2',descn:'descn2'},
        {id:3,name:'name3',descn:'descn3'},
        {id:4,name:'name4',descn:'descn4'},
        {id:5,name:'name5',descn:'descn5'},
        {id:6,name:'name6',descn:'descn6'},
        {id:7,name:'name7',descn:'descn7'},
        {id:8,name:'name8',descn:'descn8'},
        {id:9,name:'name9',descn:'descn9'}
    ]}

    請記住這個數據格式,不管後臺是什麼,只要滿足了這樣的格式要求,ext就可以接收處理,顯示到grid中。

    我這裏就不好好介紹json,現在只需要知道json裏頭除了name(名稱)就是value(值),值有好幾種格式,如果是數字就不用加引號,如果加了引號就是字符串,如果用[]包裹就是數組,如果出現{}就說明是嵌套的json。諸如此類。

    簡 單瞄了json一眼,開頭就是totalProperty:100,這告訴ext:“俺這裏有100個數據呢。”,然後就是root:[],root對應 着一個數組,數組裏有10個對象,每個對象都有id呀,name呀,descn呀。這10個數據最後就應該顯示到表格裏。

  3. jsp裏用for循環生成root數組裏的數據,這樣我們翻頁的時候可以看到數據的變化,要不每次都是一樣的數據,你怎麼知道翻頁是不是起作用了呢?

    最後我們把得到的json字符串輸出到response裏,ext也就可以獲得這些數據了。

結果經過了一番折騰,我們的jsp已經確定可以返回我們所需要的數據了。現在我們可以忘掉後臺是用什麼語言寫的了,直接切入ext代碼,看看它是怎麼樣才能跑去後臺獲得這些數據呢?

因爲引入了json作爲數據傳輸格式,這次我們要對ext代碼進行一次大換血了,請做好思想準備。

  1. 換掉proxy,別在內存裏找了,讓我們通過http獲得我們想要的。

    proxy: new Ext.data.HttpProxy({url:'grid.jsp'}),

    創建HttpProxy的同時,用url這個參數指定咱們去哪裏取數據,我們這裏設置成grid.jsp,就是我們剛纔討論的jsp腳本啦。

  2. 已經不是數組了,現在要用json咯。

    reader: new Ext.data.JsonReader({
        totalProperty: 'totalProperty',
        root: 'root'
    }, [
        {name: 'id'},
        {name: 'name'},
        {name: 'descn'}
    ])

    看比ArrayReader多了什麼?totalProperty對應咱們jsp返回的totalProperty,也就是數據的總數。root對應咱們jsp返回的root,就是一個包含返回數據的數組。

  3. 好了,最後在初始化的時候,告訴我們希望獲得哪部分的數據就可以了。

    ds.load({params:{start:0,limit:10}});

    就在ds讀取的時候添加兩個參數,start和limit,告訴後臺,我們從第一個數可以取起,最多要10個。

    在 這裏有一個小插曲,如果你按照我們以前的設置,grid是無法正常顯示的,因爲ds.load()無法在grid.render()前準備好所有數組,所 以它不知道自己應該實現多高。沒法子,我們只好爲它指定一個固定的高度了。像這樣<div id="grid" style="height:265px;"></div>。

最後,我們就可以使用分頁條上那些按鈕試試分頁了。呵呵~就這麼簡單。

1.x的例子在lingo-sample/1.1.1/02-06.html,jsp文件在lingo-sample/1.1.1/grid.jsp,下面是它的截圖:

有趣的是,1.x中,不需要爲div指定高度,它自己就知道如何顯示,不曉得爲什麼2.0裏不這樣做呢。

2.0的例子在lingo-sample/2.0/02-06.html,jsp文件在lingo-sample/2.0/grid.jsp,下面是它的截圖:

2.7.4. 其實分頁不一定要踩在腳下,也可以頂在頭上。

我的意思是,grid除了FootPanel以外,還有HeaderPanel,意思就是頭頂上的面板。我們把分頁條放在上面也不會有任何問題。1.x中的代碼僅僅是將getFooterPanel改成getHeaderPanel,這樣分頁條就跑到上頭去了。

var gridHead = grid.getView().getHeaderPanel(true);

var paging = new Ext.PagingToolbar(gridHead, ds, {
    pageSize: 10,
    displayInfo: true,
    displayMsg: '顯示第 {0} 條到 {1} 條記錄,一共 {2} 條',
    emptyMsg: '沒有記錄'
});

1.x的例子可以在lingo-sample/1.1.1/02-07.html找到。

2.0就更簡單了,只需要改一個字母,b -> t,呵呵~,讓原來的bbar(bottom bar)變成tbar(top bar)就可以讓我們的工具條登天了。

var grid = new Ext.grid.GridPanel({
    el: 'grid',
    ds: ds,
    cm: cm,
    tbar: new Ext.PagingToolbar({
        pageSize: 10,
        store: ds,
        displayInfo: true,
        displayMsg: '顯示第 {0} 條到 {1} 條記錄,一共 {2} 條',
        emptyMsg: "沒有記錄"
    })
});
發佈了5 篇原創文章 · 獲贊 2 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章