有關(guān)重大改變的幾個要點
文章內(nèi)容是對2.0新變化的綜合簡述。請留意Ext框架在從1.x跨越到2.0的過程中,經(jīng)歷了無數(shù)的細微改進、臭蟲修正和其他的改動。 要逐一列出尚難為之,所以本文著重提及架構(gòu)上有轉(zhuǎn)換的地方,和一些全新加入的功能。本文下列的各部分將完整地解釋這每一項的細節(jié)。
- 組件模型 Component Model
在1.x中就有Component和BoxComponent兩個類了,但卻沒有深入整合到框架中去。到2.0,這兩個類得到極大的改進并是一切主要組件的基礎(chǔ)。 盡管這些類對于開發(fā)者而言一般是盡量隱藏細節(jié),不過理解好組件生存周期這方面的基礎(chǔ)知識有利于進一步的Ext學(xué)習(xí)。參閱詳細。
- 容器模型 Container Model
有幾個核心類可用于生成器件(widgets)和包含其它組件的布局。 容器Container為對象的容納和組件的布局提供一個基礎(chǔ)性的構(gòu)成方式,對于整個Ext框架可視化必不可少。 面板Panel 從容器類繼承,為用戶程序提供特定功能的UI基類,屬于容器結(jié)構(gòu)層次中最常用的類。 窗口Window是面板的一種特殊類型,使得web應(yīng)用程序如桌面式(desktop-style)那樣。視見區(qū)Viewport是專為全屏幕web程序應(yīng)用而設(shè)計的實用容器 。參閱詳細
- 布局Layouts
1.x中的布局方式集中圍繞在BorderLayout和其相關(guān)的幾個類。2.0中,布局的整體架構(gòu)建立在嶄新的容器類、布局類上。 BorderLayout現(xiàn)加入到九種風(fēng)格布局之中。布局類已經(jīng)是全部重寫設(shè)計并考慮最大的可擴展性。 布局的管理亦受益于2.0的框架,去掉一些開發(fā)者之前需要面對的復(fù)雜實現(xiàn)。參閱詳細
- Grid
Grid組件往往都被認為是Ext的核心組件之一,在2.0的版本中同時繼續(xù)演進。新版的用戶界面更友好,性能更佳,功能上新加了行摘要、行歸組、和一些基于插件實現(xiàn)如expandable rows和row numbering 等等的更多功能。參閱詳細
- 模板 XTemplate
1.x的模版類處理一些簡單的模版時令人滿意,但對于復(fù)雜的輸出任務(wù)就缺乏健壯的支持。 在2.0中,全新的XTemplate可支持子模版,數(shù)組處理,直接代碼執(zhí)行,邏輯判斷和更多有用的功能。參閱詳細
- 數(shù)據(jù)視圖 DataView
1.x的模版將數(shù)據(jù)綁定到模版以生成制定的UI視圖。JsonView是快速綁定JSON數(shù)據(jù)輔助類。2.0的DataView把以上兩種方式作統(tǒng)一的處理,不同之處是它繼承自BoxComponent,可更好地支持各種布局方式,新的XTemplate類為模版處理提供強大的支持。參閱詳細
- 其它新組件
這些新組件包括動作(Action)、CycleButton、 Hidden (field)、 ProgressBar和TimeField。參閱詳細
補充說明
- 主題
2.0支持開箱即用的主題(Theme),使用更為簡化。Ext 1.x支持四套主題,但2.0減少到兩套("Ext Blue" 和Gray)。 如打算自定義Ext的主題,那么Gray主題就是一份不錯的藍本,另外一些2.0 社區(qū)主題也可以提供一些思路或直接使用。 這不是API改動的一部分,但是有需要在這里提及一下。
- 突破性進展
令人遺憾,2.0的一些改動無法做到向后兼容。因為無論相關(guān)的組件還是渲染模型已經(jīng)是從底層上大幅修改,許多現(xiàn)有的組件必須舍棄舊1.x的方式重寫編寫,與1.x的差別較大。 我們提供的1.x到2.0升級指南希望能協(xié)助解決現(xiàn)有Ext 1.x程序的升級問題。
組件模型 Component Model
組件概述
2.0的一個目標(biāo)就是希望能以簡單的代碼塊構(gòu)建程序,甚至比以往更簡單。 組件Component類最初在1.x引入,卻沒有全面整合到框架中去。在2.0中,組件所賦予的能力有長足的改進和提升,使得其成為整個架構(gòu)里最為基礎(chǔ)的一個類。組件對象為組件的創(chuàng)建、渲染、事件處理、狀態(tài)管理和銷毀提供了統(tǒng)一的模型,Ext下面的每一個組件具備了這些由組件對象擴展出來的特性。這是2.0組件對象的關(guān)鍵特性:
- 顯式聲明構(gòu)建器鏈和重寫 Explicit constructor chaining and overriding
組件會將一個基礎(chǔ)構(gòu)造器連同配置傳入到子類中。函數(shù)initComponent用于提供制定的構(gòu)造器邏輯,只要在繼承鏈上的某一個子類實現(xiàn)便可,所有的組件都遵從此方式。此時的子類就可在initComponent中對其設(shè)置相關(guān)的屬性,實現(xiàn)具體的功能。
- 可調(diào)控的渲染 Managed rendering
2.0中,每個組件都支持延時渲染(lazy rendering),又稱按需渲染(on-demand rendering)。渲染的調(diào)控一般是為你自動設(shè)置完好的。即使如此,你亦可以通過的beforerender和render事件控制渲染發(fā)生、結(jié)束,達到最為靈活的自定義調(diào)控。
- 可調(diào)控的銷毀 Managed destruction
每一個組件具有destroy的函數(shù),當(dāng)組件不再需要時,Ext就負責(zé)組件的結(jié)束調(diào)控,如自動垃圾回收和摧毀組件元素。當(dāng)然,銷毀亦提供相應(yīng)的事件,如beforedestroy和destroy可按照實際的情況作出邏輯處理。
- 狀態(tài)管理自動化 Automatic state management
組件內(nèi)建設(shè)置和獲取狀態(tài)(State)的功能,只要讓全局對象StateManager和一個狀態(tài) Provider都初始化好,那么多數(shù)的組件都具有自動狀態(tài)管理的能力。
- 組件常規(guī)行為的統(tǒng)一接口 Consistent interface for basic component behavior
一般常規(guī)的行為如隱藏、顯示和激活、禁用均是組件的基本特性。如需要,這些都可由子類去重寫或制定。
- 由組件管理器負責(zé)的可用調(diào)配 Availability via ComponentMgr
Ext的每一個組件在創(chuàng)建的時候就會由組件管理器登記注冊,即你可隨時獲取任何組件,只需調(diào)用Ext.getCmp('id')。
- 支持插件 Plugin support
現(xiàn)在任何的組件可以通過插件的形式來擴展了。插件實質(zhì)是帶有init方法的一種類。該方法會有一個單獨的參數(shù)(類型為Ext.Component)傳入到其中。插件可通過組件的plugins配置項指定。當(dāng)組件創(chuàng)建時,如果有插件可用,組件就會調(diào)用每個插件上的init方法,將自身的引用作為參數(shù)傳入。 每個插件運行之后可調(diào)用組件的方法或響應(yīng)組件的事件以實現(xiàn)自身的功能。
組件的生存周期Component Life Cycle
一般來說,組件的對象架構(gòu)滿足了“能運行(Just Works)”這一基本要求。架構(gòu)在設(shè)計上已是調(diào)控好了大多數(shù)組件是怎樣處理的,而且對最終開發(fā)者是透明的。 不過,若對組件對象擴展,或是有些需要制定的地方,就要利用一定的時間去實現(xiàn)。 深入理解組件對象的生存周期會是非常好的幫助。下面的內(nèi)容就是對基于組件的每個類,一個周期內(nèi)各個重要階段作出解釋:
初始化Initialization
- 配置項對象生效了
The config object is applied.
組件對象的構(gòu)造器會把全部的配置項傳入到其子類中去,并且進行下列所有的步驟。
- 組件的底層事件創(chuàng)建了
The base Component events are created
這些事件由組件對象負責(zé)觸發(fā)。事件有enable, disable, beforeshow, show, beforehide, hide, beforerender, render, beforedestroy, destroy (參閱Component API文檔完整的內(nèi)容)。
- 組件在組件管理器里登記了
The component is registered in ComponentMgr
initComponent這方法總是使用在子類中,就其本身而論,該方法是一個模板方法(template method),用于每個子類去現(xiàn)實任何所需的構(gòu)造器邏輯(any needed constructor logic)。首先會創(chuàng)建類,然后組件對象各層次里面的每個類都應(yīng)該調(diào)用superclass.initComponent。通過該方法,就可方便地實現(xiàn)(implement),或重寫(Override)任意一層構(gòu)造器的邏輯。
- 狀態(tài)感知進行初始化(如果有的話)
State is initialized (if applicable)
如果組件是狀態(tài)感知的,其狀態(tài)會進行刷新。
- 加載好插件(如果有的話)
Plugins are loaded (if applicable)
如果該組件有指定任何插件,這時便會初始化。
- 渲染好插件(如果必須的話)
The component is rendered (if applicable)
如果指定了組件的renderTo 或 applyTo配置屬性,那么渲染工作就會立即開始,否則意味著延時渲染,即等待到顯式控制顯示,或是其容器告知其顯示的命令。
渲染過程 Rendering
- 觸發(fā)beforerender事件 The beforerender event is fired
這是個可取消的事件,指定的句柄(handler)可阻止組件進行渲染
- 設(shè)置好容器 The container is set
如果沒有指定一個容器,那么將使用位于DOM元素中組件的父節(jié)點作為容器。
- 調(diào)用onRender方法 The onRender method is called
這是子類渲染最重要的一個步驟,由于該方法是一個模板方法(template method),用于每個子類去現(xiàn)實任何所需的渲染邏輯(any needed render logic)。首先會創(chuàng)建類,然后組件對象各層次里面的每個類都應(yīng)調(diào)用superclass.onRender。通過該方法,就可方便地實現(xiàn)(implement),或重寫(Override)任意一層渲染的邏輯。
- 組件是“隱藏”狀態(tài)的 The Component is "unhidden"
默認下,許多組件是由CSS樣式類如"x-hidden"設(shè)置隱藏的。如果 autoShow所配置的值為true,這時就不會有這個"hide"樣式類作用在該組件上
- 自定義的類、樣式生效了 Custom class and/or style applied
一切組件的子類都支持cls和style 兩種特殊的配置屬性,分別用于指定用戶自定義的CSS樣式類和CSS規(guī)則。 推薦指定cls的方法來制定組件及其各部分的可視化設(shè)置。由于該樣式類會套用在組件markup最外的一層元素,所以標(biāo)準(zhǔn)CSS規(guī)則會繼承到組件下任何子元素的身上。
- 觸發(fā)render事件 The render event is fired
這是組件通知成功渲染的一個步驟。這時,你可肯定地認為組件的DOM元素是可用的了。如果嘗試在渲染之前訪問組件,會拋出一個不可用的異常。
- 調(diào)用了afterRender方法 The afterRender method is called
這是另外一個實現(xiàn)或重寫特定所需的“后渲染”邏輯的模板方法。每個子類應(yīng)調(diào)用superclass.afterRender.
- 組件被隱藏或禁用(如果有的話) The Component is hidden and/or disabled (if applicable)
配置項hidden和disabled到這步生效
- 所有狀態(tài)感知的事件初始化(如果有的話) Any state-specific events are initialized (if applicable)
狀態(tài)感知的組件可由事件聲明特殊加載和保存狀態(tài)。如支持,加入此類的事件。
銷毀過程 Destruction
- 觸發(fā)beforedesroy事件 The beforedestroy event is fired
這是個可取消的事件,指定的句柄(handler)可阻止組件被銷毀。
- 調(diào)用了beforeDestroy方法 The beforeDestroy method is called
這是另外一個實現(xiàn)或重寫預(yù)定銷毀邏輯的模板方法。每個子類應(yīng)調(diào)用superclass.beforeDestroy。
- 元素及其偵聽器被移除 Element and its listeners are removed
若組件是渲染好的,所屬的元素的事件偵聽器和DOM樹中的元素都會被移除。
- 調(diào)用了onDestroy方法 The onDestroy method is called
這是另外一個實現(xiàn)或重寫特定所需的“后銷毀”邏輯的模板方法。每個子類應(yīng)調(diào)用superclass.onDestroy。注意 容器類(Container class,和一切容器的子類)提供了一個默認的onDestroy實現(xiàn),自動遍歷其items集合里的每一項,分別地執(zhí)行子組件身上的destroy方法。
- 在組件管理器中撤銷組件對象的登記 Component is unregistered from ComponentMgr
使得不能再從Ext.getCmp獲取組件對象
- 觸發(fā)destroy事件 The destroy event is fired
這是組件成功銷毀的一個簡單通知。此時組件已經(jīng)DOM中已是不存在的了
- 組件上的事件偵聽器被移除 Event listeners on the Component are removed
組件本身可允許從所屬的元素得到事件偵聽器。如有的話,連同刪除。
組件的X類型 XTypes
XTypes是Ext 2.0中新的概念,被認為是Ext組件的特定類型。可用的xtype摘要可在 Component類API開始的地方找到。與一般JavaScript對象用法相似,XTypes可用于查找或比較組件對象,如isXType和getXType等的方法。其中getXTypes的方法可列出任意組件的xtpye層次表。
然而,Xtypes最大的用途是怎么用于優(yōu)化組件的創(chuàng)建和渲染過程。 通過指定一個xtype的配置對象的寫法,可隱式聲明的方式創(chuàng)建組件,使得當(dāng)不需要立即渲染的情況就只是一個對象,省去不必要的實例化步驟。這時不僅渲染的動作是延時的,而且創(chuàng)建實際對象的這一步也是延時的,從而節(jié)省了內(nèi)存和資源。 在復(fù)雜的布局中,這種性能上的改進尤為明顯。
//顯式創(chuàng)建所容納的組件
var panel = new Ext.Panel({
...
items: [
new Ext.Button({
text: 'OK'
})
]
};
//使用xtype創(chuàng)建
var panel = new Ext.Panel({
...
items: [{
xtype: 'button',
text: 'OK'
}]
};
第一個例子中,面板初始化的同時,按鈕總是會立即被創(chuàng)建的。如果加入較多的組件,這種方法很可能減慢的渲染速度。第二例子中,按鈕直到面板真正在瀏覽器上需要顯示才會被創(chuàng)建和渲染。
如果面板從未顯示(例如有個tab一直是隱藏的),那么按鈕就不會被創(chuàng)建,不會消耗任何資源了。
BoxComponent
BoxComponent 是另外一個重要的基類,該類從組件Component擴展,為任何要進行可視渲染和參與布局的組件提供了一致的、跨瀏覽器的箱子模型(Box Model)實現(xiàn)。BoxComponent負責(zé)調(diào)節(jié)大小和定位,自動處理各瀏覽器之間的差異,如外/內(nèi)補丁、邊框的問題,形成一個統(tǒng)一的箱子模型,以支持各種瀏覽器。2.0的一切容器類(container)繼承自BoxComponent。
容器模型Container Model
Ext 2.0 Component/Container Class Hierarchy
容器 Container
一個組件如果有包含其它的組件,那么,容器Container便是這個組件奠基之石。該類提供了布局方面和調(diào)節(jié)大小、嵌套組所需的邏輯,并且提供一個基礎(chǔ)性的加入組件協(xié)調(diào)機制。容器類不應(yīng)該直接使用,其目的在于為一切可視的容器組件提供一個基類。
面板 Panel
面板Panel是2.0最常用的容器,90%布局任務(wù)都離不開面板。布局里的排版元素便是面板,面板如同一張白紙,完全是空白的矩形,沒有可視內(nèi)容。雖然這樣,面板也提供了一些預(yù)留區(qū)域, 方便加入程序所需的UI界面,包括頂部或底部的工具條、菜單欄、頭部區(qū)域、底部區(qū)域和軀干區(qū)域。同時內(nèi)建可展開和可收縮行為的按鈕,和其它不同任務(wù)預(yù)設(shè)的按鈕。面板可輕松地下降到任意的容器或布局,當(dāng)中定位或渲染的邏輯全部由Ext調(diào)控,
下列是Ext 2.0面板最主要的幾個子類:
Window
Window 是一種可浮動的、可最小/最大化的、可復(fù)原的、可拖動的..等此類的特殊面板。其目的在于實現(xiàn)一種具有桌面風(fēng)格的程序界面的基類,像Ext桌面演示看到的那樣。
視見區(qū)Viewport
視見區(qū)Viewport是以document.body作容器的實用類,它會與瀏覽器視圖自適應(yīng)尺寸,是全屏幕應(yīng)用的基礎(chǔ),如瀏覽器大小調(diào)節(jié)、布局重新計算的問題由該類自動完成。 注意視見區(qū)Viewport除了document.body元素外不能渲染在其它的容器上,所以一個頁面只能有一個視見區(qū)。
布局 Layouts
Ext 2.0 Layout Class Hierarchy
引言
2.0中最具意義的改進之一。在創(chuàng)建優(yōu)雅的程序布局時感受到易用性或靈活性方面帶來的好處。在Ext 1.x,布局的開發(fā)集中圍繞在BorderLayout、Region和ContentPanel幾個類。 1.x BorderLayout已經(jīng)可以方便地生成UI,但要真正創(chuàng)建屬于自己的布局,還是沒有足夠的支持。 創(chuàng)建復(fù)雜的布局通常需要手工編寫一些代碼應(yīng)付滾動條、嵌套和某些怪癖的問題。
Ext 2.0帶來了一個重寫編寫的、企業(yè)級應(yīng)用的布局管理系統(tǒng)。 共有10種風(fēng)格的布局管理器,分別提供構(gòu)建各種可能的程序布局基礎(chǔ)。Ext調(diào)控了布局諸如size、定位、滾動條和其他的屬性方面的問題,一如既往地簡單,開箱即用。在容器也可無限嵌套布局、混合其他不同風(fēng)格的布局。
布局由容器內(nèi)置創(chuàng)建,所以布局不應(yīng)通過關(guān)鍵字new實例化這種方式直接使用。 有一種內(nèi)部的機制,容器與布局能夠很好地協(xié)調(diào)工作—只需配置好相關(guān)的參數(shù),容器就會委托其負責(zé)的布局類工作。創(chuàng)建容器的時候,你應(yīng)選定一種布局的風(fēng)格以及相關(guān)的配置,這兩個配置是屬性layout和屬性layoutConfig。 舉例:
var panel = new Panel({
title: 'My Accordion',
layout: 'accordion', //在這個面板中所使用的布局樣式
layoutConfig: {
animate: true //布局指定的配置項寫在這里
}
// 其他Panel的選項
});
當(dāng)你創(chuàng)建嵌套布局時,明白面板包含其他面板是很重要的,布局中的每個面板必須指定一個布局管理器。 多數(shù)情況你不需要指定布局的風(fēng)格如“border”或“accordion”,較常見的是“fit”那一種,會自動調(diào)整大小自適應(yīng)它的容器。 如果你不指定某個布局管理器,默認的是ContainerLayout類,不過這樣很可能導(dǎo)致一些意料不到的情況發(fā)生,所以最好精確聲明一下。
每種布局類都支持其特定的配置選項。關(guān)于布局每種配置選項可參考API文檔。
布局管理器 Layout Managers
Grid
概述
2.0中的GridView有極大的改進,而Grid的UI部分,正是由GridView這個類來實現(xiàn)的。2.0中GridView最主要的新功能有:
- 效能的提升
GridView的底層結(jié)構(gòu)和渲染代碼已在2.0完整重構(gòu)過,并側(cè)重考慮了效能部分。正因性能的原因,鎖定列的這一功能已經(jīng)取消(參閱下一節(jié))。
- 感觀(look and feel)的改進
和新2.0的主題一起, Grid的外觀控制也有新變化,使得Grid比以前更時尚和看上去更具吸引力。
- 單行歸組
多個行可被歸組到某一指定列,由用戶重新歸組亦可。
- 多行組摘要
每一組可相應(yīng)的提供一個數(shù)據(jù)摘要組
- 進階插件支持
在2.0中,新加入插件機制。GridView就是這種插件機制的一個典型例子。如范例中所示,Grid優(yōu)秀的功能便是依靠幾個預(yù)先做好的插件。插件RowExpander提供了展開、收縮行的功能,插件RowNumberer就提供了行中數(shù)字的支持。
列鎖定的注意事項(Column Locking)
有些用戶或許發(fā)現(xiàn)Ext 1.x中列鎖定的功能,到2.0因為已經(jīng)取消,并可以說以后也不再支持了。列鎖定(Column locking),雖然對某些用戶來說有其的用途, 但與2.0 GridView的新功能有不兼容的地方(如歸組、摘要等),而且為了實現(xiàn)鎖定會使得Grid渲染性能開銷增大。 因此,1.x gridView這功能的向上升級,或打補丁,均不會由官方支持。
注意:當(dāng)前有為2.0而做的用戶擴展在進行中,以實現(xiàn)2.0的列鎖定,而且看上去寫得還蠻不錯。更多有用資訊可論壇的帖子找到。
XTemplate
XTemplate使用了多種標(biāo)簽和特殊操作符支持模板,使得模板在應(yīng)付復(fù)雜的數(shù)據(jù)結(jié)構(gòu)時尤為健壯。這里所列出的高度概括的幾項功能,欲了解完整的細節(jié)和使用方法,請參閱XTemplate API文檔.
- 自動數(shù)組填充和作用域切換
- 可在子模板作用域內(nèi)訪問父級對象
- 可訪問數(shù)組索引
- 支持數(shù)據(jù)值的簡單匹配
- 自動渲染浮點型數(shù)組(不包含非對象的值)
- 基礎(chǔ)性的條件邏輯符號if
- 可執(zhí)行模板中直接寫好的任意語句
- 支持模板的配置屬性
- 可通過配置項對象自定義模板方法
- 可用于服務(wù)端的JavaScript模板
DataView
從表面上看,DataView跟1.x的View類非常相似。兩者都支持模版數(shù)據(jù)渲染,Data store數(shù)據(jù)綁定和內(nèi)建的選區(qū)模型和事件。但是, 隨著2.0新架構(gòu)的設(shè)計,DataView賦予了更強大的功能。 下面是這次最重要的改動:
- 繼承自BoxComponent
1.x View類繼承自O(shè)bservable, 作為獨立組件而言工作不錯, 但是它并沒提供內(nèi)建的機制與其他組件融合的能力。而DataView就是針對這種不足作出的改進,該類從BoxComponent繼承,因此如前文所述,也具備一般組件的生存周期控制。
- 發(fā)揮了XTemplate之功效
1.x View類采用了1.x本身的模版類Template 。較好滿足了view自身的需求,但是難以滿足一些復(fù)雜的渲染任務(wù)。DataView采用的模版類也升級到2.0的XTemplate,可輕松定制UI應(yīng)付復(fù)雜的數(shù)據(jù)。
- 新增的配置選項
DataView 提供了更為靈活的-幾個新選項:
- itemSelector: 必須是一個DomQuery選擇符告知該類究竟如何分辨出每個item。相比1.x的做法帶來更高的靈活性和更高的速度。
- simpleSelect: 一種新的選區(qū)生成模式,使得用戶無須按下Shift或Ctrl鍵便可進行多選。
- overClass: 一個CSS的樣式類,每個元素onmouseover和onmouseout時生效。
- loadingText:像其他綁定store的Ext組件一樣,DataView支持標(biāo)準(zhǔn)的遮罩效果。
其它新組件
一些有趣的新組件也加入到2.0中去了。要了解這些新組件到底有什么新功能,最好還是看看API文檔完整的介紹。
動作 Action
動作Action是一種從組件中抽象出來的可復(fù)用的“功能塊”,即多個組件之間的同一功能都來自這個ACTION的實現(xiàn)。動作允許你共享句柄(handlers),配置選項和UI的更新,所有組件均支持動作的接口(主要是Toolbar,Button和 Menu組件)。 詳細在API文檔。
CycleButton
這是一個包含復(fù)選元素菜單的特制的SplitButton。當(dāng)菜單子項每次被單擊,按鈕都會輪回一次狀態(tài),觸發(fā)change的事件(或調(diào)用按鈕的changeHandler函數(shù),如果有的話)以激活菜單項。 FeedViewer演示程序就包含了該例子— 預(yù)覽窗口地址的那個按鈕就是一個SplitButton。詳細在API文檔。
Hidden (field)
這個便是HTML表單中隱藏域的一個簡單的實現(xiàn),能夠以EXT FORM組件般操控。詳細在API參考。
進度條 ProgressBar
1.x中的進度條是簡單地內(nèi)建在MessageBox類中。現(xiàn)在已重構(gòu)為單獨的器件并有進一步的改進。它支持兩種不同的模式(手動和自動進度),而且LOOK and FEEL方面可輕松制定。詳細在API參考。
TimeField
這是下拉列表時間選取器的簡單實現(xiàn)。詳細在API參考。