小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

ExtJS 4 組件詳解

 nikybook 2015-07-30

ExtJS 4 的應用界面是由很多小部件組合而成的,這些小部件被稱作“組件(Component)”,所有組件都是Ext.Component的子類,Ext.Component提供了生命周期管理包括初始化、渲染、大小和尺寸管理、銷毀等功能,這使得所有Ext.Component的子類都自動分享了這些能力。ExtJS提供了各式各樣豐富的組件,每一個組件都很容易被擴展創(chuàng)建成自定義組件。

The Component Hierarchy 組件層級

容器(Container)是個可以容納其他組件的特殊組件。通常的應用都是由很多嵌套的組件構(gòu)成,這些組件有一個類似樹狀的結(jié)構(gòu),這就是組件的層級。容器負責管理子組件的生命周期包括始化、渲染、大小和尺寸管理、銷毀。通常的應用最頂層的組件都是Viewport然后有其他容器或者組件嵌套在其中:

component_hierarchy

子組件通過容器的items加入到容器中,下面這個例子通過Ext.create方法創(chuàng)建了兩個Panel,并把它們當作子組件添加到Viewport中:

1
2
3
4
5
6
7
8
9
10
11
12
13
var childPanel1 = Ext.create('Ext.panel.Panel', {
    title: 'Child Panel 1',
    html: 'A Panel'
});

var childPanel2 = Ext.create('Ext.panel.Panel', {
    title: 'Child Panel 2',
    html: 'Another Panel'
});

Ext.create('Ext.container.Viewport', {
    items: [ childPanel1, childPanel2 ]
});

容器通過“布局管理器(Layout Manager)”管理子組件的尺寸和位置。關(guān)于布局和容器的詳細內(nèi)容可以查看《ExtJS 4 布局和容器

XTypes and Lazy Instantiation xtype和延遲加載

每個組件都有一個代稱叫做xtype,例如Ext.panel.Panelxtypepanel。所有組件的xtypeAPI Docs for Component 中有列出。上面那個例子說明了如何添加已經(jīng)初始化的組件到一個容器中。在大的應用中,這種方式是不可行的,因為這種方法需要每個組件都是初始化過的,但是大的應用中,由于使用的方式有些組件可能根本沒有被用到(比如有100個頁面的應用,一個用戶登錄進來只操作了兩個頁面,這時把其他98個頁面的組件全部初始化是不合理的),例如一個用到TabPanel的應用,TabPanel的每個tab只當用戶點擊它的時候再渲染即可。這就是引入xtype機制的原因,有了xtype可以讓一個容器的子組件事先定義好,到真正需要的時候再初始化。

下面的示例代碼通過TabPanel展示了延遲加載和延遲渲染,每個tab都有個響應函數(shù)監(jiān)聽tab的渲染render事件,渲染的時候會彈出一個對話框告知當前tab已經(jīng)渲染

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Ext.create('Ext.tab.Panel', {
    renderTo: Ext.getBody(),
    height: 100,
    width: 200,
    items: [
        {
            // Explicitly define the xtype of this Component configuration.
            // This tells the Container (the tab panel in this case)
            // to instantiate a Ext.panel.Panel when it deems necessary
            xtype: 'panel',
            title: 'Tab One',
            html: 'The first tab',
            listeners: {
                render: function() {
                    Ext.MessageBox.alert('Rendered One', 'Tab One was rendered.');
                }
            }
        },
        {
            // this component configuration does not have an xtype since 'panel' is the default
            // xtype for all Component configurations in a Container
            title: 'Tab Two',
            html: 'The second tab',
            listeners: {
                render: function() {
                    Ext.MessageBox.alert('Rendered One', 'Tab Two was rendered.');
                }
            }
        }
    ]
});

運行一下代碼,第一個tab的渲染對話框馬上就彈出了,因為默認激活第一個tab,所以它的父容器TabPanel立即初始化和渲染了它

lazy_render1

不點擊第二個tab,它的對話跨就一直不會彈出,這說明tab不會被渲染直到被用到,tab的render事件不會觸發(fā)直到tab被激活

lazy_render2

Showing and Hiding 顯示和隱藏

所有組件都有內(nèi)置的showhide方法。默認的css樣式應用的是display: none,可以通過hideMode改變

1
2
3
4
5
6
7
8
9
10
var panel = Ext.create('Ext.panel.Panel', {
    renderTo: Ext.getBody(),
    title: 'Test',
    html: 'Test Panel',
    hideMode: 'visibility' // use the CSS visibility property to show and hide this component
});

panel.hide(); // hide the component

panel.show(); // show the component

Floating Components 浮動組件

浮動組件定位于文檔流之外,使用的是CSS的絕對定位屬性,不受父容器的布局控制。有些組件,例如Window,默認就是浮動的,任何組件都可以通過floating屬性配置成浮動的。

1
2
3
4
5
6
7
var panel = Ext.create('Ext.panel.Panel', {
    width: 200,
    height: 100,
    floating: true, // make this panel an absolutely-positioned floating component
    title: 'Test',
    html: 'Test Panel'
});

上面的代碼實例化了一個Panel對象,但是并沒有渲染它。通常一個組件要么有renderTo屬性配置渲染到什么位置,要么就作為容器的一個子組件由容器負責渲染,但是這個例子的浮動組件即不需要renderTo也不需要作為子組件。浮動組件第一次調(diào)用show方法時,會被自動渲染到DOM的document.body中:

1
panel.show(); // render and show the floating panel

有幾個屬性是使用浮動組件時值得注意的:

  • draggable - 讓浮動組件可以拖拽
  • shadow - 定制浮動組件的陰影效果
  • alignTo() - 讓浮動組件對齊到一個特定元素
  • center() - 讓浮動組件相對于容器居中

Creating Custom Components 自定義組件

Composition or Extension 組合還是繼承

當創(chuàng)建一個新的UI類時,必須決定這個類是引用其他組件的實例還是擴展這個組件。
推薦擴展最接近的組件添加自己需要的功能,這是因為使用繼承的方式可以自動獲得組件原有的自動生命周期管理能力,包括按須渲染、布局管理器提供的尺寸位置管理、從容器中刪除的自動析構(gòu)等。
擴展一個原有組件會讓擴展出的組件隸屬于組件層級中,這樣比一個外部類引用并掌管ExtJS組件的實例要容易的多。

Subclassing 子類化

ExtJS的類系統(tǒng)使得擴展一個現(xiàn)有組件變的很簡單。接下來的代碼演示了創(chuàng)建一個Ext.Component的子類,不添加任何功能:

1
2
3
Ext.define('My.custom.Component', {
    extend: 'Ext.Component'
});

Template Methods 模板方法

ExtJS使用了模板方法模式把特殊行為委托給子類。
這意味著每一個繼承鏈上的類都可以“貢獻”一段包含特定邏輯的片段到組件的生命周期中。每一個類實現(xiàn)自己特殊行為的同時,還允許其他在繼承鏈上的類繼續(xù)貢獻它們自己的邏輯。
一個例子就是render方法。render是個私有方法,是在Component的父類AbstractComponent中定義的,render在組件生命周期中負責渲染階段的初始化。render不能被重寫,但是render過程中會調(diào)用onRender,這個onRender方法是允許子類去實現(xiàn)的,子類可以在這里增加專屬于子類的邏輯,每一個onRender方法必須在自己的額外邏輯之前調(diào)用父類的onRender。
下圖指示了onRender模板方法是如何工作的。
render方法首先被調(diào)用(這是布局管理器完成的),render方法不能被覆蓋,它是ExtJS中的相關(guān)基類實現(xiàn)的,它會調(diào)用當前子類的this.onRender(如果當前子類有實現(xiàn)onRender),這會使得繼續(xù)調(diào)用父類的onRender,父類的onRender會繼續(xù)調(diào)用父類的,最后每個繼承鏈上的類都貢獻了自己的功能片段,并且控制回到render方法中。

template_pattern

這有一個實現(xiàn)onRender的例子

1
2
3
4
5
6
7
8
Ext.define('My.custom.Component', {
    extend: 'Ext.Component',
    onRender: function() {
        this.callParent(arguments); // call the superclass onRender method

        // perform additional rendering tasks here.
    }
});

需要注意的是很多模板方法都有一個對應的事件。例如組件render完成之后會觸發(fā)render事件。創(chuàng)建子類的時候最好是使用模板方法,而不是使用事件,因為模板方法一定會被執(zhí)行,事件是可以被中斷的(這里是我的補充:什么時候用事件,什么時候用模板方法?模板方法是面向你創(chuàng)建的子類的所有實例的,如果你需要增加的功能片段確實被所有實例需要,那一定要放在模板方法中,如果是某一個實例特殊需要的功能,請用事件實現(xiàn),事件是可以對單獨某個對象實現(xiàn)的)
下面列舉的是Component的子類中可以實現(xiàn)的模板方法:

  • initComponent 這個方法被構(gòu)造器調(diào)用,它被用來初始化數(shù)據(jù),設(shè)置配置,添加事件
  • beforeShow 這個方法在組件顯示前調(diào)用
  • onShow 允許組件顯示的時候附加行為,調(diào)用父類的onShow之后,組件變?yōu)榭梢?/li>
  • afterShow 這個方法在組件顯示完成后調(diào)用
  • onShowComplete 這個方法在afterShow執(zhí)行完畢的時候調(diào)用
  • onHide 允許組件隱藏的時候附加行為,調(diào)用父類的onHide之后,組件變?yōu)椴豢梢?/li>
  • afterHide 這個放在組件隱藏完成后調(diào)用
  • onRender 允許在渲染階段附加行為
  • afterRender 允許在渲染完畢時附加行為,在這個階段,組件的Element已經(jīng)賦予了樣式,該加的css類都已經(jīng)加上,顯示和啟用與否的狀態(tài)都標記完成
  • onEnable 允許啟用操作時附加行為,調(diào)用父類的onEnable之后,組件變?yōu)閱⒂?/li>
  • onDisable 允許禁用操作時附加行為,調(diào)用父類的onDisable之后,組件變?yōu)榻?/li>
  • onAdded 允許一個組件被添加到一個容器的時候附加行為,在這個階段,組件已經(jīng)在父容器的items中,調(diào)用父類的onAdded之后,ownerCt引用被設(shè)置,如果配置了ref,refOwner這時也被設(shè)置
  • onRemoved 允許一個組件從父容器中刪除的時候附加行為,在這個階段,組件已經(jīng)從父容器的items中移除,但是還沒有被銷毀(如果父容器的autoDestroy設(shè)置為true,或者如果刪除操作remove函數(shù)的第二個參數(shù)設(shè)置為true,組件就會被銷毀),調(diào)用父類的onRemoved之后,ownerCt和refOwner就會移除
  • onResize 允許改變大小的時候附加行為
  • onPosition 允許設(shè)置位置的時候附加行為
  • onDestroy 允許銷毀時附加行為,調(diào)用父類的onDestroy之后,組件被銷毀
  • beforeDestroy 組件銷毀前調(diào)用
  • afterSetPosition 組件位置設(shè)置之后調(diào)用
  • afterComponentLayout 組件布局完成時調(diào)用
  • beforeComponentLayout 組件布局之前調(diào)用

Which Class To Extend 擴展那個類

選擇最合適的類繼承是個影響效率的問題,基類能提供的功能也是個問題?,F(xiàn)在有種傾向是無論什么樣的UI組件都從Ext.Panel繼承
Panel類有很多能力:

  • Border
  • Header
  • Header tools
  • Footer
  • Footer buttons
  • Top toolbar
  • Bottom toolbar
  • Containing and managing child Components

如果不需要這些功能,繼承Ext.Panel是浪費資源。

Component 組件

如果創(chuàng)建的UI組件不需要包含任何其他組件,就比如只是對HTML片段的封裝就可以滿足需求的組件,推薦擴展Ext.Component,例如下面的例子封裝了HTML image元素,允許設(shè)置image的src,并且圖片加載完成會觸發(fā)load事件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Ext.define('Ext.ux.Image', {
    extend: 'Ext.Component', // subclass Ext.Component
    alias: 'widget.managedimage', // this component will have an xtype of 'managedimage'
    autoEl: {
        tag: 'img',
        src: Ext.BLANK_IMAGE_URL,
        cls: 'my-managed-image'
    },

    // Add custom processing to the onRender phase.
    // Add a ‘load’ listener to the element.
    onRender: function() {
        this.autoEl = Ext.apply({}, this.initialConfig, this.autoEl);
        this.callParent(arguments);
        this.el.on('load', this.onLoad, this);
    },

    onLoad: function() {
        this.fireEvent('load', this);
    },

    setSrc: function(src) {
        if (this.rendered) {
            this.el.dom.src = src;
        } else {
            this.src = src;
        }
    },

    getSrc: function(src) {
        return this.el.dom.src || this.src;
    }
});

用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var image = Ext.create('Ext.ux.Image');

Ext.create('Ext.panel.Panel', {
    title: 'Image Panel',
    height: 200,
    renderTo: Ext.getBody(),
    items: [ image ]
})

image.on('load', function() {
    console.log('image loaded: ', image.getSrc());
});

image.setSrc('http://www./img/sencha-large.png');

這個例子僅作為例子,Ext.Img可以在真實應用中使用。

Container 容器

如果UI組件需要包含其他組件的能力,但是又不需要Panel那么多功能Ext.container.Container是個很好的選擇。使用它有一點需要注意,記得使用Layout管理子組件。
Ext.container.Container有如下模板方法:

  • onBeforeAdd 這個方法在添加一個子組件之前調(diào)用,方法會被傳入添加進來的子組件,你可能會對子組件進行一些修改,或者對容器自身做一些準備工作,返回false會中斷添加操作。
  • onAdd 這個方法在新組件被添加完成時調(diào)用,方法會傳入新添加的組件,這個方法可以用來更新依賴子組件狀態(tài)的內(nèi)部結(jié)構(gòu)
  • onRemove 子組件被刪除之后調(diào)用,用處跟onAdd類似
  • beforeLayout 組件布局它的子組件之前調(diào)用的方法
  • afterLayout 組件布局它的子組件之后調(diào)用的方法

Panel 面板

如果需求的UI組件必須有header,footer或者toolbar,Ext.panel.Panel比較適合
注意Panel也是個容器,也需要Layout管理子組件
Panel擴展出的組件一般都是跟具體應用相關(guān)的,通常都聚合了其他組件在其中,一般都提供了操作內(nèi)部組件的方法,比如在toolbar上有操作內(nèi)部組件的按鈕等
Panel有如下附加的模板方法:

  • afterCollapse 組件折疊起來之后調(diào)用
  • afterExpand 組件展開之后調(diào)用,與afterCollapse相對應
  • onDockedAdd 工具條上有子組件添加之后調(diào)用
  • onDockedRemove 工具條上有子組件被移除后調(diào)用

更多教程

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多