EXT JS4 mvc模式及实例

有许多MVC体系结构,其中大多数都是彼此略有不同。这是EXT JS4中的。
    模型:字段和数据的集合。模型知道如何通过数据包存储,能通过协议连接到其他模型。
    视图:任何类型的组件——网格、树和面板是所有视图。    
    控制器:存放所有使应用程序工作的代码的地方——不管是渲染的视图,实例化模型,或任何其他应用程序逻辑。

一、文件结构

EXT JS4中应用遵循统一的目录结构,所以每一个应用程序都是相同的。在MVC布局中,所有的类都放在了app文件夹,该文件夹依次包含了存放模型、视图、控制器和存储的文件夹。

Folder Structure

二、实战代码

1.index.html

<html>
<head>
    <title>Account Manager</title>

    <link rel="stylesheet" type="text/css" href="ext-4.0/resources/css/ext-all.css">

    <script type="text/javascript" src="ext-4.0/ext-debug.js"></script>

    <script type="text/javascript" src="app.js"></script>
</head>
<body></body>
</html>

2.app.js

Ext.application({
    requires: 'Ext.container.Viewport',
    name: 'AM',

    appFolder: 'app',

    launch: function() {
        Ext.create('Ext.container.Viewport', {
            layout: 'fit',
            items: [
                {
                    xtype: 'panel',
                    title: 'Users',
                    html : 'List of users will go here'
                }
            ]
        });
    }
});

3.定义控制器

Users.js:

Ext.define('AM.controller.Users', {
    extend: 'Ext.app.Controller',

    init: function() {
        console.log('Initialized Users! This happens before the Application launch function is called');
    }
});

添加新建的Users 控制器到app.js中的应用配置中:

Ext.application({
    ...

    controllers: [
        'Users'
    ],

    ...
});

当用应该程序在浏览器上访问 index.html 时,Users控制器会自控装载(因为我们指定它在应用定义以上),init 函数在应用程序的launch函数启动之前被调用。

init 函数是一个很棒的地方来来简历控制器如何与视图交互 ,通常是与另一个控制器函数——control结合使用。control函数使得它容易监听视图类中的事件,并对处理函数采取一些措施。更新ourUsers控制器,设定什么时候渲染面板,Users.js:

Ext.define('AM.controller.Users', {
    extend: 'Ext.app.Controller',

    init: function() {
        this.control({
            'viewport > panel': {
                render: this.onPanelRendered
            }
        });
    },

    onPanelRendered: function() {
        console.log('The panel was rendered');
    }
});
control函数使用ComponentQuery引擎,以快速方便地得到页面上的参考部件。 'viewport > panel'可翻译成"find every Panel that is a direct child of a Viewport"。然后,我们提供了一个对象映射事件名(例子中只有渲染)处理功能。整体效果是无论何时任何组件匹配到选择器(即 'viewport > panel')时,触发render事件,onPanelRendered函数被调用。

Controller listener

4.定义视图

视图通常定义成Ext .JS .component的子类, List.js
Ext.define('AM.view.user.List' ,{
    extend: 'Ext.grid.Panel',
    alias : 'widget.userlist',

    title : 'All Users',

    initComponent: function() {
        this.store = {
            fields: ['name', 'email'],
            data  : [
                {name: 'Ed',    email: 'ed@sencha.com'},
                {name: 'Tommy', email: 'tommy@sencha.com'}
            ]
        };

        this.columns = [
            {header: 'Name',  dataIndex: 'name',  flex: 1},
            {header: 'Email', dataIndex: 'email', flex: 1}
        ];

        this.callParent(arguments);
    }
});
我们有可能继承Grid Component,建立一个别名(alias),以便可以用它作为一个xtype。
然后添加这个视图到Users控制器中,由于我们用 'widget.'格式设置了一个别名,我们可以用'userlist'作为一个xtype,就像先前用的 'panel'一样。Users.js:
Ext.define('AM.controller.Users', {
    extend: 'Ext.app.Controller',

    views: [
        'user.List'
    ],

    init: ...

    onPanelRendered: ...
});

通过修改app.js中的launch函数,把它渲染到主视图中:

Ext.application({
    ...

    launch: function() {
        Ext.create('Ext.container.Viewport', {
            layout: 'fit',
            items: {
                xtype: 'userlist'
            }
        });
    }
});
'user.List'告诉应用程序自动加载文件。

Our first View

5.控制网格

修改User.js:
Ext.define('AM.controller.Users', {
    extend: 'Ext.app.Controller',

    views: [
        'user.List'
    ],

    init: function() {
        this.control({
            'userlist': {
                itemdblclick: this.editUser
            }
        });
    },

    editUser: function(grid, record) {
        console.log('Double clicked on ' + record.get('name'));
    }
});
我们改变了 ComponentQuery 选择器( 'userlist'),事件名称 ( 'itemdblclick'),处理函数名称 ( 'editUser')。

Edit.js
Ext.define('AM.view.user.Edit', {
    extend: 'Ext.window.Window',
    alias : 'widget.useredit',

    title : 'Edit User',
    layout: 'fit',
    autoShow: true,

    initComponent: function() {
        this.items = [
            {
                xtype: 'form',
                items: [
                    {
                        xtype: 'textfield',
                        name : 'name',
                        fieldLabel: 'Name'
                    },
                    {
                        xtype: 'textfield',
                        name : 'email',
                        fieldLabel: 'Email'
                    }
                ]
            }
        ];

        this.buttons = [
            {
                text: 'Save',
                action: 'save'
            },
            {
                text: 'Cancel',
                scope: this,
                handler: this.close
            }
        ];

        this.callParent(arguments);
    }
});
我们再一次使用initComponent来指定复杂对象items和buttons。
添加视图到控制器,渲染并加载它。Users.js:
Ext.define('AM.controller.Users', {
    extend: 'Ext.app.Controller',

    views: [
        'user.List',
        'user.Edit'
    ],

    init: ...

    editUser: function(grid, record) {
        var view = Ext.widget('useredit');

        view.down('form').loadRecord(record);
    }
});
我们用方法 Ext.widget创建了一个视图,相当于 Ext.create('widget.useredit')。然后我们用ComponentQuery再次快速获取一个编辑窗口的表单,在Ext JS 4中,每个组件都有一个down函数,该函数接受ComponentQuery选择器来找子组件。

6.创建一个模型和一个存储

app/store/Users.js

Ext.define('AM.store.Users', {
    extend: 'Ext.data.Store',
    fields: ['name', 'email'],
    data: [
        {name: 'Ed',    email: 'ed@sencha.com'},
        {name: 'Tommy', email: 'tommy@sencha.com'}
    ]
});
让Users控制器加载时包括这个store,修改app/ controller/Users.js:
Ext.define('AM.controller.Users', {
    extend: 'Ext.app.Controller',
    stores: [
        'Users'
    ],
    ...
});
修改 app/view/user/List.js
Ext.define('AM.view.user.List' ,{
    extend: 'Ext.grid.Panel',
    alias : 'widget.userlist',

    //we no longer define the Users store in the `initComponent` method
    store: 'Users',

    ...
});
app/model/User.js
Ext.define('AM.model.User', {
    extend: 'Ext.data.Model',
    fields: ['name', 'email']
});
修改控制器和存储:
//the Users controller will make sure that the User model is included on the page and available to our app
Ext.define('AM.controller.Users', {
    extend: 'Ext.app.Controller',
    stores: ['Users'],
    models: ['User'],
    ...
});

// we now reference the Model instead of defining fields inline
Ext.define('AM.store.Users', {
    extend: 'Ext.data.Store',
    model: 'AM.model.User',

    data: [
        {name: 'Ed',    email: 'ed@sencha.com'},
        {name: 'Tommy', email: 'tommy@sencha.com'}
    ]
});

7.用模型保存数据

更新控制器,使它能监听save按钮:

Ext.define('AM.controller.Users', {
    init: function() {
        this.control({
            'viewport > userlist': {
                itemdblclick: this.editUser
            },
            'useredit button[action=save]': {
                click: this.updateUser
            }
        });
    },

    updateUser: function(button) {
        console.log('clicked the Save button');
    }
});
'useredit button[action=save]':用 'useredit' xtype来 聚焦道正在编辑的用户窗口,然后在窗口中寻找拥有 'save' action的任何按钮。

编辑save按钮事件:

updateUser: function(button) {
    var win    = button.up('window'),
        form   = win.down('form'),
        record = form.getRecord(),
        values = form.getValues();

    record.set(values);
    win.close();
}
button.up('window')找到正在编辑的用户窗口, win.down('form')找到表单

8.保存到服务器

使用ajax:

Ext.define('AM.store.Users', {
    extend: 'Ext.data.Store',
    model: 'AM.model.User',
    autoLoad: true,

    proxy: {
        type: 'ajax',
        url: 'data/users.json',
        reader: {
            type: 'json',
            root: 'users',
            successProperty: 'success'
        }
    }
});
我们移除了 'data'属性,用‘porxy’来代替。在EXT JS4中proxy是一种从一个store或模型中加载和保存数据的方法,有AJAX, JSON-P 和HTML5 porxy。例子中加载的数据来自于 'data/users.json'

创建data/users.json

{
    success: true,
    users: [
        {id: 1, name: 'Ed',    email: 'ed@sencha.com'},
        {id: 2, name: 'Tommy', email: 'tommy@sencha.com'}
    ]
}
对proxy做一点小变化
proxy: {
    type: 'ajax',
    api: {
        read: 'data/users.json',
        update: 'data/updateUsers.json'
    },
    reader: {
        type: 'json',
        root: 'users',
        successProperty: 'success'
    }
}
仍旧从users.json中读数据,但任何修改都会发送到 updateUsers.json 中。 updateUsers.json文件中仅仅包含 {"success": true}.
updateUser: function(button) {
    var win    = button.up('window'),
        form   = win.down('form'),
        record = form.getRecord(),
        values = form.getValues();

    record.set(values);
    win.close();
    this.getUsersStore().sync();
}
告诉store编辑之后,同步它自己。

The record in the grid has been updated



  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值