1. 程式人生 > >Extjs 6.2 實戰 (二)MVVM模式介紹

Extjs 6.2 實戰 (二)MVVM模式介紹

MVVM是模型(Model)、檢視(View)和檢視模型(ViewModel)的縮寫,是一種軟體設計模式。

MVVM主要作用就是簡化事件驅動變成的使用者介面開發。

它把軟體系統劃分為模型、檢視和檢視模型三個基本部分

2.1 Extjs中的MVVM模式

 Extjs中的MVVM模式將應用程式劃分為檢視、檢視控制器和檢視模型三個部分,

模型:用來顯示資料的各種UI元件,如模板(Ext.Template)、資料檢視(Ext.view.View)、網格(Ext.grid.Panel)或圖表(Ext.chart.Chart)等元件。

檢視控制器:一般是指從Ext.app.ViewController擴充套件的類,用於維護檢視的邏輯。它的生命週期是包含在檢視的生命週期中的,會隨檢視的建立而建立,隨檢視的銷燬而銷燬。同一個檢視,建立了多少個例項,也會相應的建立多個檢視控制器的例項,而不會想ExtJs4那樣,無論多少個檢視例項,都只對一個控制器,從而造成控制器不知道該去操控哪個檢視的問題,也解決了控制器銷燬的問題。

模型:一般是指從Ext.data.Model擴展出來的模型類。

檢視模型:一般是指從Ext.app.ViewModel擴充套件的類,用於管理檢視的資料。

2.2 元件查詢機制

ExtJs6中引入了醫用機制來獲取元件,但很多時候還是需要使用到元件查詢來獲取元件,因而熟練掌握並瞭解元件查詢物件是必不可少的。

2.21 元件管理器:Ext.ComponentManager

元件能夠實現查詢全靠元件管理器,因為在建立元件例項時都需要在元件管理器中註冊,在Ext.Component類的建構函式中可以看到以下程式碼

constructor:function(config){

    var me = this,

......

        if(!me.preventRegister){

               Ext.ComponentManager.register(me);

         }

.......

}

在ExtJs6中,Ext.Component是所有元件的根類,而元件在初始化的時候,都會在建構函式中呼叫callParent方法來執行父類的建構函式,直至根類的建構函式。也就是說,無論元件繼承層次有多深,都會執行Ext.Component的建構函式。從上面所列的Ext.Component的建構函式的程式碼的粗體程式碼中可以看到,如果沒有生命preventRegister為true,就會呼叫Ext.ComponentManager的register方法來註冊元件例項。

register: function(){

    var me = this;

        all = me.all,

        key = component.getId(),

        onAvailableCallbacks = me.onAvalilableCallbacks;

    //<debug>

    if(key == undefined){

        Ext.raise('Component id is undefined. Please ensure the component has an id.');

    }

    if(key in all){

       Ext.raise('Registering duplicate component id "' + key + '"');

     }

    //<debug>

    all[key] = component;

    if(component.getReference && component.getReference()){

        me.references[key] = component;

    }

    ++me.count;

    if(!me.hasFocusListener){

        Ext.on('focus', me.onGlobalFocus, me);

        me.hasFocusListener = true;

    }

    onAvailableCallbacks = onAvailableCallbacks && onAvailableCallbacks[key];

    if(onAvailableCallbacks && onAvailableCallbacks.length){

        me.notifyAvailable(component);

    }

}

從粗體程式碼可以看到,register方法會通過元件的getId方法返回組建的識別符號,並把該識別符號作為all物件的屬性名稱,而該屬性的屬性值為元件。

每當建立元件例項的時候,都會在元件管理器中進行註冊,也就是將元件例項儲存到一個物件中,通過元件的識別符號就可以輕鬆的找到這個元件。

2.2.2 元件的查詢方式

1、使用id進行查詢

    Ext.ComponentQuery.query("#mypanel");

2、根據元件的別名進行查詢(xtype)

    Ext.ComponentQuery.quer("panel");

    Ext.ComponentQuery.query(".panel");

3、使用屬性查詢

    Ext.ComponentQuery.query("panel[title=我的面板]");

4、使用成員函式進行查詢

    Ext.ComponentQuery.query("{成員函式}");

    例如要查詢被禁用的按鈕

    Ext.ComponentQuery.query("{isDisabled()}");

5、偽類查詢

    元件查詢還可以想DOM查詢一樣實現偽類查詢,不過目前只定義了not這樣一個偽類查詢,目的是用來查詢不匹配選擇符的元件

2.2.3 直接使用id查詢元件

    Ext.getCmp = function(id){

        return Ext.ComponentManager.get(id);

    }

這裡呼叫了Ext.ComponentManager的get方法,它的原始碼如下:

 get : function(id){

    return this.all.get(id);

 }

2.2.4 元件中的查詢

元件中的查詢依賴與元件樹,往上可追溯父元件,往下可查詢子元件。

元件中的查詢主要包括 up、down、query、child、nextNode、nextSibiling、previousNode和previousSibling這8個方法。

1、Ext.Component的up方法

        Ext.Component的up方法的作用是查詢當前元件的父元件。

2、Ext.Container的down方法

        down方法是在Ext.Container中定義的,用來查詢子元件。

        down方法的使用與up方法的區別不大,需要注意的是,down方法返回的是符合條件的第一個元件,而且只能在容器類   及其子類中使用。

3、Ext.Container的query方法

      query方法返回的是由元件組成的陣列。剩下的使用方法與up跟down方法沒什麼區別。

4、Ext.Container的child方法

      返回容器下直接元件的第一個子元件。

5、Ext.Component的nextNode、nextSibiling、previousNode和previousSibling方法

      這4個方法是用來查詢當前元件的前一個節點或下一個節點的。nextNode(previousNode)與nextSibiling(previousSibiling)的主要區別是nextSibiling查詢的是與當前節點同層的節點,而nextNode則沒有這個限制。

2.3 檢視控制器

檢視控制器相對於ExtJs4的控制器來說,最大的區別就在於檢視控制器採用的是宣告式事件監聽

比如:

{xtype : 'button', text : '儲存', handler : 'onSave'}

定義了一個儲存按鈕,handler配置項應該是一個函式,以實現按鈕的單機操作,而現在定義的是一個方法名稱,這就是宣告式事件監聽。

那這個是怎麼實現的呢?在sencha內部,把這一過程稱為事件監聽作用域解析,簡單來說就是在元件或檢視控制器內搜尋對應的方法。搜尋會先從元件所在的檢視或檢視控制器開始,如果沒有找到,就會沿著元件樹往上一層層的找,直到找到對應的方法。實在找不到就會丟擲錯誤。

由於檢視控制器與檢視是一對一的關係,因此在檢視控制器中引入以下4個方法來對應檢視的關鍵點任務:

beforinit : 該方法會在檢視的initComponent方法執行之前執行。該方法如果放在initComponent方法內,就相當與在呼叫callParent方法之前的程式碼,如調整子元件等操作。

init : 該方法會在initComponent方法執行之後執行,也就是在initComponent方法內呼叫callParent方法之後的程式碼,如呼叫on方法為子元件繫結事件等操作。

initViewModel : 該方法會在檢視模型(如果定義了檢視模型)建立之後執行。

destory : 清理和回收資源。如果檢視需要多次建立和銷燬,且在檢視內建立了Ext.util.KeyNav之類的物件,就必須在該方法內銷燬物件,以防止出現記憶體洩漏。在該方法內,千萬別忘了呼叫callParent方法以執行父類的清理工作。

2.4 檢視模型

檢視模型的主要作用是用來管理用於繫結的資料物件。在檢視模型中常用的配置項主要包含data、formulas、和stores。

data主要用來定義除了儲存之外的任務資料物件,它的值為配置物件。在配置物件中,每一個屬性為一個數據物件,如面板的標題希望通過繫結的方式來實現切換,就可在定義面板時新增以下程式碼來實現繫結:

bind : {title : '{title}'}

配置項bind表示這裡的內容要實現繫結操作。屬性title表示要繫結面板的標題屬性,而要繫結的資料物件為title.

formulas主要作用是可以對data內的資料物件做一些運算後返回運算結果,如為網格繫結selecion屬性以便獲取選擇行:

bind : {selection : '{selected}'}

希望在檢視模型中獲取選擇行內某列的資訊,如title列,就可以在formulas配置項內定義一個getTitile的方法來獲取選擇行的標題:

data : {

    selected : null

}

formulas : {

    getTitle : function(){

        var selected = get('selected');

        if(Ext.isEmpty(selected)) return ' ';

        return selected.data.title;

    }

}

store主要用來定義檢視所需的儲存

stores : {

    users : {

    ...............

    },

    roles : {

    ...............

    }

}

如果元件需要繫結儲存,就可以通過類似如下程式碼的方式來繫結儲存:

bind : {store : '{users}'}