Ext Js之ComboBox詳解(第二部分)-------譯


 

ComboBox被完全集成於Extjs 的數據包當中。這就使他在下拉列表中的的數據被限定在數據倉庫當中(data store)。在其帶來豐富的優點的同時,也帶來了許許多多的易發錯誤的來源。在本部分我會試着闡明一個帶有store配置項的combobox。



一:明確的建立一個Store對象。

  在之前的一篇文章當中。我介紹了一些常用的combobox的配置選項。但是有一個在每個例子中都用到的配置選項Store我卻沒有進行介紹。這個配置選項包含了一個包含下拉列表的數據的數組。

Ext.create('Ext.form.field.ComboBox', { 
store: ['Red', 'Yellow', 'Green', 'Brown', 'Blue', 'Pink', 'Black'] 
});

 

  然而,如果列表中的數據在進行開發的時候並不能預先知曉的話。這樣的內置數據的配置方式就會帶來非常非常多的不便。對於一個存有大量數據的列表。一次就把他們全部加載進來時相當的不切實際的。這樣的話,一些服務器端的過濾和分頁就需要被部署。

  提供一個內聯的數據,會隱式的建立一個完整的Store對象。這里有三種方式來提供對配置store對象的完全控制。

第一種方式就是制定store對象為一個內聯的配置項

Ext.create('Ext.form.field.ComboBox', { 
    store: { 
      fields: ['text'], 
      data: [ 
              {text: 'Red'}, 
              {text: 'Yellow'},  
              {text: 'Green'}, 
                    ... 
            ] 
           } 
});

 


第二種傳遞store對象的方式,先建立一個store對象,然后再傳遞給Combobox對象

 

var store = Ext.create('Ext.data.Store', { 
fields: ['text'], 
data: [ 
{text: 'Red'}, 
{text: 'Yellow'}, 
{text: 'Green'}, 
... 
] 
}); 

Ext.create('Ext.form.field.ComboBox', { 
store: store 
});

 

 


第三種方式傳遞的是一個store對象的id

Ext.create('Ext.data.Store', { 
fields: ['text'], 
storeId: 'my-store', 
data: [ 
{text: 'Red'}, 
{text: 'Yellow'}, 
{text: 'Green'}, 
... 
] 
}); 

Ext.create('Ext.form.field.ComboBox', { 
store: 'my-store' 
});

 

雖然以上的三種配置方式當中的數據仍舊是內嵌的。但是現在這些配置已經是store對象的一部分,而不是直接在combobox當中進行配置。 從combobox的視角來看數據是可以來自任何地方的,而combobox看到的僅僅是一個store對象(就是說這些數據只要放在store當中,然后把這個store對象傳遞給我,我就能夠顯示數據,而不是非要報數據寫在combobox當中我才能顯示數據)。數據的格式經過了輕微的改動以適應store的數據格式。每一個store對象都有一個fields配置選項,其默認值為text。

如果你嘗試了上面三個例子當中的一個的話,你就會發現他們的表現跟本來的那些例子有所不同。新的表現的方式是相當的奇怪的。而且難以徹底弄清楚其中的緣由。稍后我們會看到一個例子,但是為了更好的理解它,我們就必須先了解combobox是如何處理遠程數據的。




三:遠程數據


使用store配置選項,而不用內置的數據的一項主要原因就是,這使得加載從服務器而來的遠程的數據更加的簡單。來讓我們先看一些簡單的例子吧。這里面還有一些新出現的配置選項需要解釋一下。

Ext.create('Ext.form.field.ComboBox', { 
queryMode: 'local', 
store: { 
autoLoad: true, 
fields: ['text'], 
proxy: { 
type: 'ajax', 
url: 'snooker-balls.json' 
} 
} 
});

 

其中store的autoLoad配置選項被配置為true,所以啊,他就會在自己被創建的之后盡快的加載數據。然后proxy對象就會利用AJAX方式與給定的服務器和URL交互,以此來獲取數據。

JSON從服務器端返回的數據大概是這個樣子
[ 
{"text": "Red"}, 
{"text": "Yellow"}, 
{"text": "Green"}, 
{"text": "Brown"}, 
{"text": "Blue"}, 
{"text": "Pink"}, 
{"text": "Black"} 
]

 

 

你可以自己試試下面的例子,這些數據會在store被創建之后盡快的加載進來。因此這些數據看起來就像是在本地存儲的一樣快。


到目前為止我還沒有介紹為什么這個神秘莫測的queryMode配置選項被設置為了local數據明明是從遠方的服務器加載來的,那么為什么這個配置選項還是被設置成了local模式呢?
在前面的一篇文章當中我們碰到過一個配置選項是這樣的triggeraction:'query'正如我們在那篇文章中看到的那樣。在combobox的上下文語義中,query的意義實際上指的是過濾下拉列表中的值。

在對queryMode進行翻譯的時候如果我們也這樣考慮的話, 那么這個配置選項的方式就會有更多的意義。盡管列表中的值是被遠程加載進來的。但是過濾這項操作仍然是在本地完成的。當用戶輸入文本數據的時候,下拉列表的就會在本地被過濾,其並不需要向服務器端進行更進一步的查詢操作。

在 ExtJs 4 之前的版本當中。queryMode被簡單的指明為mode,這就導致了許許多多的疑惑,因為這個名字沒有暗示它實際上到底做了什么。

 

 


四:遠程過濾


從遠程的服務器獲取一個列表的數據非常好用。但是這又是遠遠不夠的。要是我們有非常非常多的數據,以至於在瀏覽器端進行過濾會變得非常的不現實。我們需要做的第一個改變就是更改queryMode:'remote',因為這種配置是默認的,所以我們可以直接把這個配置選項給去掉。同樣的,我們也需要把autoLoad;truep 配置選項給去掉,這時store就不會立刻去服務器端加載數據。

Ext.create('Ext.form.field.ComboBox', { 
store: { 
fields: ['text'], 
proxy: { 
type: 'ajax', 
url: 'snooker-balls.json' 
} 
} 
});

 


然而故事講到這里才講到了一半,服務器必須被設置為可以用來立刻進行過濾操作利用上面的配置方式,如果我們鍵入blac的話,combobox會發送一個請求,大概是這個樣子。

snooker-balls.json?query=blac&...

 

為了讓這個例子完成其功能。服務器就必須明白如何返回一個被過濾后的數據。請求中的參數query可以被改變,我們只需要設置,queryParam,但是對於這個例子默認的名字就挺好。


對於這個例子還有一些問題,
在鍵入四個字符之前,什么都不會發生。單擊箭頭還是會將所有的數據展現出來。在我們假想的情況下這樣就會有太多的數據被加載。下面我們按順序一個個的處理這些問題。首先當使用遠程過濾的時候,minchars
配置選項可以設置的范圍是0到4.這就可以防止數據在達到四個字符長度之前被傳送到服務器。有時候當數據未達到指定的長度的時候我們不希望發送這些字符用來在服務器端進行過濾,但是對於我們本例中較小的數據集合,這個需求就不是那么迫切了。所以我們可以把它下調為1.

Ext.create('Ext.form.field.ComboBox', { 
minChars: 1, 
store: { 
fields: ['text'], 
proxy: { 
type: 'ajax', 
url: 'snooker-balls.json' 
} 
} 
});

 


禁止下拉箭頭觸發查詢操作被證明是相當簡單的。在前面的文章中我們可以看到。設置triggerAction:‘query’將會強制trigger根據當前的值進行過濾查詢的操作。這也涉及到了minchar配置選項。因此單擊trigger或者按下向下鍵將不會有任何的功能。


Ext.create('Ext.form.field.ComboBox', { 
minChars: 1, 
triggerAction: 'query', 
store: { 
fields: ['text'], 
proxy: { 
type: 'ajax', 
url: 'snooker-balls.json' 
} 
} 
});

 

 


到目前為止一切看起來都挺好的。下面我們簡單的使用前一章中學過的配置信息來配置這個例子。emptyText,hideTrigger,typeahead

 

Ext.create('Ext.form.field.ComboBox', { 
emptyText: 'Colour', 
hideTrigger: true, 
minChars: 1, 
triggerAction: 'query', 
typeAhead: true, 
store: { 
fields: ['text'], 
proxy: { 
type: 'ajax', 
url: 'snooker-balls.json' 
} 
} 
});

 


五:分頁
即使使用遠程過濾的方式。數據還是有可能因為過於龐大而不能一次顯示所有的可選選項。有時候我們有充分的理由只去顯示少量的滿足條件的數據。但是在其他的情況下提供一個分頁的操作是更加明智的選擇。

store上最常用的配置選項就是一些最最基本的ExtJs的分頁配置信息。這個combobox被配置的寬度width為260.這是為了給分頁的工具條提供空間。這里有兩個pagesize的配置選項,一個在store中另一個在combobox當中。兩個都是必須的,但是在combobox里面的那個做了一些額外的事情,它告訴combobox去展現一個分頁的工具條。設置它為true跟將他設置為具體的數值都是一個效果。

Ext.create('Ext.form.field.ComboBox', { 
minChars: 0, 
pageSize: true, // This just causes a paging toolbar to show 
triggerAction: 'query', 
width: 260, 
store: { 
fields: ['text'], 
pageSize: 5, 
proxy: { 
type: 'ajax', 
url: 'css-colors.json', 
reader: { 
root: 'data', // Must match the property in the JSON response 
type: 'json' 
} 
} 
} 
});

 

根據上面的配置信息一個典型的請求大概會是這個樣子

css-colors.json?query=b&page=1&start=0&limit=5&...

 


limit就是page size,start需要顯示的頁面的第一條數據的索引值從0開始page指的是頁號。從1開始。在請求數據中存在一些冗余的信息。

服務器強制完負責分頁的功能。如果服務器返回的數據超過五個,他們就會全部的被顯示到列表當中。

 

JSON的返回數據大概就是這個樣子:

{ 
"total": 8, 
"data": [ 
{"text": "Beige"}, 
{"text": "Bisque"}, 
{"text": "Black"}, 
{"text": "BlanchedAlmond"}, 
{"text": "Blue"} 
] 
}

 

 


total的值指明store中有8個結果滿足查詢然而卻只有5個被返回了。對於page size只有5,所以被解析成了兩頁。

 

六:明確的建立store,重復訪問
在本文剛剛開始的時候。我們看到了怎么把內置的數據轉移到一個store當中。讓我們再回顧一下前面提到的例子。

Ext.create('Ext.form.field.ComboBox', { 
store: { 
fields: ['text'], 
data: [ 
{text: 'Red'}, 
{text: 'Yellow'}, 
{text: 'Green'}, 
... 
] 
} 
});

 

很明顯這個例子表現的不正確。下拉列表直到第四個字符被輸入才顯示出來。而且即使他出現了,它也沒有被過濾。這個問題我們前面曾經遇到過,當我們使用combobox的queryMode:‘remote’配置選項的時候。
這就能解釋為什么過濾的操作會失敗了。簡而言之當數據在本地的時候使用遠程過濾的方式是沒有任何的意義的。下一段就嘗試這對此進行更加深入的闡述。但是這會需要對ExtJs的數據包的知識有一些了解。



設置queryMode為remote就能防止其本身對數據進行過濾。代替的是,它僅僅告訴store去加載和傳遞相關的已經被過濾的選項。store並不直接加載數據,而是傳遞這些選項到proxy當中去。對於一個使用本地數據的store,proxy對象是被隱含建立的。而且是一個包裝到數據對象之上的memory proxymemory proxy是相當的純天然,他總會返回數據集合當中的所有值。它甚至都不能理解分頁操作是個怎么回事。
更別說是過濾操作了。因此,當用戶進行輸入的時候combobox會一直請求store加載數據但是這也沒什么分別,因為proxy總會返回所有的數據。

下面的例子中我們需要將我們的例子中使用queryMode;'local'

Ext.create('Ext.form.field.ComboBox', { 
queryMode: 'local', 
store: { 
fields: ['text'], 
data: [ 
{text: 'Red'}, 
{text: 'Yellow'}, 
{text: 'Green'}, 
... 
] 
} 
});

 


但是這又帶來了其他的一些問題,為什么在使用本地數據的時候就不需要設置queryMode了呢?問題的答案其實很俗,當我們指定內聯數據的時候combobox會自動的轉變queryMode為local。

 

七:在不同的combobox之間分享store

一個UI界面經常有好幾個combobox使用同一個數據集合,在不同的combobox當中分享store是非常的具有吸引力的。但是這也會帶來許許多多的問題。下面的例子就分享了同一個store對象。其中的數據被存放在本地。一開始兩個combobox工作的相當好。但是如果多進行一會兒操作的話。就會發現在兩個combobox當中的下拉列表被泄露了。(you'll find that the filtering of the drop-downs leaks between the two comboboxes.)一個需要知曉的關鍵點是,過濾的操作被應用於store而不是combobox因此分享一個store仍然會分享同一個過濾方法。分享store只有在列表不被過濾的情況下才能正確工作。比如當設置editable:false。



 

 




 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM