Extjs 的MVVM结构学习笔记

本文介绍了Extjs 5.0引入的MVVM模式,详细解析了Model、View、Controller和ViewModel的角色与功能。ViewModel作为View和Model的中介,直接管理数据绑定和公式。此外,还讲解了Store的使用,包括如何获取Store对象和配置数据源。
摘要由CSDN通过智能技术生成

  Extjs 5.0之后引入的MVVM模式。MVVC模式是在MVC模式之上加了一个ViewModel层。

  • model:Model is a collection of fields and their data (e.g. a User model with username and password fields). Models know how to persist themselves through the data package, and can be linked to other models through associations. Models work a lot like the Ext JS 3 Record class, and are normally used with Stores to present data into grids and other components. model是数据和变量的集合(user模式自带用户名和密码这两个变量)。model知道如何通过数据包维护他们,并且可以通过associations关联到其他的model。models和record的工作方式很想,通常使用stores来将数据呈现到grid或其他组件里面。
  • view:View is any type of component - grids, trees and panels are all views.view是任何类型的组建-grids,trees,panels都是view
  • controller:Controllers are special places to put all of the code that makes your app work - whether that's rendering views, instantiating Models, or any other app logic。controller是一个用于放置应用逻辑的地方,包括views的,models或其他的业务逻辑。
  • viewModel:The ViewModel is an abstraction of the view that mediates changes between the View and an associatedModel. In the MVC pattern, this would have been the responsibility of a specialized Controller, but in MVVM, the ViewModel directly manages the data bindings and formulas used by the View in question.viewmodel是view的一个抽象,它展示了view和关联model之间的变化。在mvc模式中,这种变化由一个特殊的controller负责,但是在mvvc中,viewmodel直接管理view使用的数据binding和formulas.
  • 结构如图:
                                  
    需要注意的是并不是所有的view都需要一个viewmodel。但是当他们被使用的时候,每一个相关的view都会创建一个viewmodel,这意味着可能存在一个viewmodel的多个实例。
下面以example里面的email代码为例,说明下这几个模块是怎么结合的。
  首先定义一个全局视图容器类:
 
Ext.define('Admin.view.email.Email', {
    extend: 'Ext.container.Container',

    xtype: 'email',

    controller: 'email',

    viewModel: {
        type: 'email'
    },

    itemId: 'emailMainContainer',

    layout: {
        type: 'hbox',
        align: 'stretch'
    },

    margin: '20 0 0 20',

    items: [
        {
            xtype: 'container',

            itemId: 'navigationPanel',

            layout: {
                type: 'vbox',
                align: 'stretch'
            },

            width: '30%',
            minWidth: 180,
            maxWidth: 240,

            defaults: {
                cls: 'navigation-email',
                margin: '0 20 20 0'
            },

            items: [
                {
                    xtype: 'emailmenu',
                    listeners: {
                        click: 'onMenuClick'
                    }
                },
                {
                    xtype: 'emailfriendslist'
                }
            ]
        },
        {
            xtype: 'container',
            itemId: 'contentPanel',
            margin: '0 20 20 0',
            flex: 1,
            layout: {
                type : 'anchor',
                anchor : '100%'
            }
        }
    ]
});
  说明:
首先定义了一个类Admin.view.email.Email,类似于java里面的public class xxx。extend是继承。该类的类型是email(email是别名),controller引用email,viewmodel引用email。该全局view的id是emailMainContainer。之后定义了它的layout和margin。item里面包含了这个全局viewport里面包含的东西,即两个containers。
之后定义两个item的view。
Ext.define('Admin.view.email.Inbox', {
    extend: 'Ext.grid.Panel',

    alias: 'widget.emailinbox',

    cls: 'email-inbox-panel shadow-panel',

    viewModel: {
        type: 'emailinbox'
    },

    bind: {
        store: '{EmailInbox}'
    },

    viewConfig: {
        preserveScrollOnRefresh: true,
        preserveScrollOnReload: true
    },

    selModel: {
        selType: 'checkboxmodel',
        checkOnly: true,
        showHeaderCheckbox: true
    },

    listeners: {
        cellclick: 'onGridCellItemClick'
    },

    headerBorders: false,
    rowLines: false,

    columns: [
        {
            dataIndex: 'favorite',
            menuDisabled: true,
            text: '<span class="x-fa fa-heart"></span>',
            width: 40,
            renderer: function(value) {
                return '<span class="x-fa fa-heart'+ (value ? '' : '-o') +'"></span>';
            }
        },
        {
            dataIndex: 'from',
            text: 'From',
            width: 140
        },
        {
            dataIndex: 'title',
            text: 'Title',
            flex: 1
        },
        {
            dataIndex: 'has_attachments',
            text: '<span class="x-fa fa-paperclip"></span>',
            width: 40,
            renderer: function(value) {
                return value ? '<span class="x-fa fa-paperclip"></span>' : '';
            }
        },
        {
            xtype: 'datecolumn',
            dataIndex: 'received_on',
            width: 90,
            text: 'Received'
        }
    ]
});
说明:这是一个表格。
  cls表明应用的样式是email-indox-panel shadow-panel。
  定义viewmodel是emailinbox,viewModel即当前视图的viewModel实例是什么,viewModel的参数值可以是viewMode的别名字符串,也可以是ViewModel带完整   命名空间的类路径的字符串形式,也可以是viewModel的配置实例对象。
  关联的数据集是EmailInbox。bind即数据绑定,把Model数据绑以key-value形式暴露出去,view视图里可以采用{key}这种表达式来引用Model里的数据。
  viewConfig:是关于该view的一些配置,这里将preserveScrollOnRefresh和preserveScrollOnReLoad都设置为true。
之后定义Inbox.js的viewmodel。
Ext.define('Admin.view.email.InboxViewModel', {
    extend: 'Ext.app.ViewModel',

    alias: 'viewmodel.emailinbox',

    stores: {
        EmailInbox: {
            //Store reference
            type: 'emailinbox'
        }
    }
});
说明:
ViewModel的关键在于data和stores,这里没有指明data。
  data指的是此时此刻model的数据。
  stores可以定义多个数据源,EmailInbox数据源的引用别名,可以通过grid.getStore("store引用名")来获取这里的数据源,后面的type是EmailInbox定义的别名,即表示这里的Store是哪个类的实例。如果有多个store你可以这样:

stores: {
    aaa: {type: ""xx.xxxx.AA""},

    bbb: {type: ""xx.xxxx.BB""}

}

外部通过getStore("aa"),getStore("bb")这样来获取Store对象,后面的xx.xxx.AA是Store类的完整类路径(包含命名空间)。

然后在store里面绑定数据源。

Ext.define('Admin.store.email.Inbox', {
    extend: 'Ext.data.Store',
    requires:["Admin.model.email.Email"],
    alias: 'store.emailinbox',

    model: 'Admin.model.email.Email',

    pageSize: 20,

    autoLoad: true,

    proxy: {
        type: 'ajax',
        url: '~api/email/inbox',
        reader: {
            type: 'json',
            rootProperty: 'data'
        }
    }
});

说明:

store类的关键就是指定model和proxy。这里引用的数据源是Admin.model.email.Email.proxy设置读取方式是json,读取的数据是data字段。store需要的数据都以json字符串的形式定义在inbox.json文件里。Store是依赖于Model的,所以requires里需要引入Email类.


之后在data/email/inbox里面定义需要显示的数据即可。

      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值