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;


    //

    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 + '"');

     }

    //

    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}'}





你可能感兴趣的:(Extjs 6.2 实战 (二)MVVM模式介绍)