95992828九五至尊2

中的MVC应用架构,数据显示和询问

一月 20th, 2019  |  882828九五至尊手机版

本篇初叶效仿一个船只管理连串,提供查询、添加、修改船舶的效劳,那里介绍其中的数据展现和询问成效。

一、ExtJs 4.x MVC格局的原理与效果

科普客户端应用一般不佳达成倒霉社团也不佳维护,因为效益和人工的穿梭充实,那一个使用的范围神速就会超越掌控能力,ExtJS4带来了一个新的运用架构,不但可以团体代码,还足以削减完结的情节。

新的行使架构依据一个类MVC的格局,模型(Models)和控制器(Controllers)第一次被引入。业界有很多种MVC架构,基本龙岩小异,ExtJS4的定义如下:

a.Model模型:模型是字段和它们的多寡的聚合,例如User模型带有username和password字段,模型知道怎么样持久化自己的数目,并且能够和其他模型关联,模型跟ExtJS
3
中的Record类有点像(差异是,Record只是但是的扁平结构,而Model可以nest),平时都用在Store中去浮现grid和此外零件的数量。

b.View视图:视图是组件的一种,专注于界面显得 – grid, tree, panel
都是view。

c.Controllers控制器:一个内置所有使您的app正确工作的代码的岗位,具体一点相应是颇具动作,例如咋样渲染view,咋样起始化model,和app的其他逻辑。

请留心:MVC是一个框架,不是设计形式,越多的情节请参考:
百度健全

框架与设计格局尽管一般,但却有所根本的不等。设计形式是对在某种环境中一再次出出现的题材以及缓解该问题的方案的叙说,它比框架更抽象;框架可以用代码表示,也能一向实施或复用,而对形式而言唯有实例才能用代码表示;设计格局是比框架更小的要素,一个框架中反复带有一个或几个设计情势,框架连接针对某一特定应用领域,但一样形式却可适用于各类应用。可以说,框架是软件,而设计格局是软件的知识。

简单的说:设计形式是大智慧,用来对软件设计进行分工;框架模式是小技巧,对切实问题提议解决方案,以拉长代码复用率,下落耦合度。

目录

1.
数码展示

2.
多少查询

  1. 在线演示

 

二、ExtJs 4 MVC框架搭建

1. 多少展现

在此间大家将效仿一个船只管理连串,并提供查询、添加、修改的效用。

差不离的目录结构如下:

882828九五至尊手机版 1

ShipMgrTab.js :船舶业务的输入。

controller 目录:存放船舶业务的逻辑控制文件。

model 目录:存放船舶业务的model文件。

store 目录 :存放船舶业务的store文件。

view 目录 :存放船舶业务的组件文件。

2.1、文件结构

ExtJS 4 应用都根据一个统一的目录结构,每个应有都一模一样
MVC中,所有类都放在app目录里面,那个目录可以有子目录,代表的是命名空间(一个子目录对应一个命名空间),使用区其他目录存放views,models,controllers,stores。当大家完毕例子的时候,目录结构应该和下图一律:

882828九五至尊手机版 2

ExtJS
SDK必须的文本在目录ext4中,由此,index.html应该引入extjs必须的js和css,以及app.js文件

1.1 设定Model

在显示数据从前要先做一些准备作用,比如工作与服务器数据交互的格局。

Model表示事情的实业对象,在此地设定船舶的Model:

Ext.define('App.ShipMgr.model.ShipModel', {
    extend: 'Ext.data.Model',
    fields: [
        { name: 'ShipId', type: 'string', remark: '船舶ID' },
        { name: 'ShipName', type: 'string', remark: '船舶名称' },
        { name: 'State', type: 'string', remark: '状态' },
        { name: 'StateName', type: 'string', remark: '状态名称' },
        { name: 'Tonnage', type: 'string', remark: '吨位' },
        { name: 'LoadNumber', type: 'int', remark: '核载人数' },
    ]
});  

  

 

2.2、在app.js中开创应用

每个ExtJS
4的接纳都从一个Application882828九五至尊手机版,类的实例先河,那个实例包罗应用的大局配置(例如利用的名字),这一个实例也承担爱惜对一切模型、视图、控制器的引用的掩护,还有一个launch函数,会在所有加载项加载成功未来调用。

第一须求选用一个大局命名空间,所有ExtJS4应用都需求有一个大局命名空间,以让抱有应用中的类安置到里面:

Ext.application({
    requires: ['Ext.container.Viewport'],  
    name: 'FWY',//定义的命名空间
    appFolder: 'app',//指明应用的根目录
    launch: function() {
        Ext.create('Ext.container.Viewport', {
            layout: 'fit',
            items: [
                {
                    xtype: 'panel',
                    title: '标题',
                    html : '内容'
                }
            ]
        });
    }
});    

1.2 设定Store

Store打包了一个Model对象的缓存,通过 Proxy 加载数据,并提供了对数据开展排序、筛选和询问的效劳。 (在此地只是不难写出须求的Model和Store;若须要对Mode、
Store和Proxy三者具体涉及的垂询可以访问 http://docs.sencha.com/extjs/4.2.1/#!/guide/data)

var shipMgrStore = Ext.create('Ext.data.Store', {
    model: 'App.ShipMgr.model.ShipModel',
    pageSize: 25,
    autoLoad: true,
    proxy: {
        type: 'ajax',
        url: '/Business/ShipMgr/Query',
        reader: {
            reader: 'json',
            root: 'data',
            totalProperty: 'rowCount',
        },
        actionMethods: {
            create: 'Post'
        }
    }
});

 

2.3、定义一个控制器

控制器是选取的粘合剂,它们所作的事情就是监听事件并进行动作,继续大家的使用,创制一个控制器。创立app/controller/Students.js以此文件,并丰裕如下代码:

Ext.define('FWY.controller.Students', {
    extend: 'Ext.app.Controller',
    init: function() {
        console.debug("trigger controller init event");
    }
});    

接下去在app.js中添加对Students控制器的引用:

Ext.application({
...
controllers: [
    'Students'  //对应于controller文件夹下面的Students.js
],
...
});

当我们经过index.html查看应用,Students控制器会被机关加载(因为在app.js的Application中加进了引用),并且Students的init方法会在launch从前调用。

init措施是个极好的地方,可以用来安装哪些和view交互,平日都施用Controller的一个方式control,control方法使得监听view的事件变的简单,更新一下控制器,让它报告大家panel曾几何时渲染:

Ext.define('FWY.controller.Students', {
    extend: 'Ext.app.Controller',
    init: function() {
        this.control({
            'viewport > panel': {
                render: this.onPanelRendered
            }
        });
    },
    onPanelRendered: function() {
        console.debug('该panel被渲染了');
    }
});

我们已经更新了init方法,使用this.controll给视图设置监听器。那一个controll方法,使用新型的组件查询引擎(ComponentQuery)可以便捷方便的找到页面上的零部件。假如您对ComponentQuery不熟谙,可以查阅ComponentQuery文档举办详尽了然。简要一点,ComponentQuery能够允许大家使用一个近似css选取器的不二法门找到组件。

在例子的init方法中大家使用了’viewport >
panel’,能够分解为“查找Viewport间接后代中的所有Panel组件”,然后大家提供了一个目的匹配事件名称(那个例子中只用了render)来提供响应函数。全体的熏陶就是不管哪个组件符合大家的选取器,当它的render事件触发时,我们的onPanelRendered函数都会被调用。

1.3 创建Grid组件

Grid组件常用语业务中数量的列表显示。

// 创建grid
var shipMgrGrid = Ext.create('Ext.grid.Panel', {
    store: shipMgrStore,
    columnLines: true,
    rowLines: true,
    bbar: Ext.create('Ext.toolbar.Paging', {
        store: shipMgrStore,
        pageSize: 25,
        displayInfo: true,
        displayMsg: '当前显示第{0}行到第{1}行,一共{2}行。',
        emptyMsg: '没有任何记录'
    }),
    columns: [
        Ext.create('Ext.grid.RowNumberer', {
            text: '序号',
            width: 50
        }), {
            text: '船舶名称',
            dataIndex: 'ShipName',
            flex:1
        }, {
            text: '状态名称',
            dataIndex: 'StateName',
            width: 150
        }, {
            text: '吨位',
            dataIndex: 'Tonnage',
            width: 150
        }, {
            text: '核载人数',
            dataIndex: 'LoadNumber',
            width: 150
        }
    ]
});

 

三、创建ExtJs4 MVC应用

1.4 服务器重临的数额格式

在此间shipMgrStore接收的是json格式的多寡:

{"success":true,
"rowCount":100,
"data":[
{"ShipId":"989f1ace-5961-46d4-8f93-b56decb893af","ShipName":"船舶1","StateName":"离线","Tonnage":1.0,"LoadNumber":1},
{"ShipId":"f4dc1dd9-a173-4822-b3d3-4b3caa12820b","ShipName":"船舶2","StateName":"在线","Tonnage":1.0,"LoadNumber":1},
{"ShipId":"7b33d073-412b-460d-8e43-4f2d061d39a0","ShipName":"船舶3","StateName":"在线","Tonnage":2.0,"LoadNumber":2},
{"ShipId":"6ad72f6d-a4e6-4637-ab8b-038b9a7fc1b1","ShipName":"船舶4","StateName":"离线","Tonnage":3.0,"LoadNumber":3},
{"ShipId":"c3614867-a722-4ca8-961f-1324d5da4ad2","ShipName":"船舶5","StateName":"在线","Tonnage":1.0,"LoadNumber":4},
{"ShipId":"526befcf-0202-45b6-8175-4ca29a698acb","ShipName":"船舶6","StateName":"在线","Tonnage":5.0,"LoadNumber":1},
{"ShipId":"058295b4-e4d6-4fb6-b232-ed0e07515571","ShipName":"船舶7","StateName":"离线","Tonnage":6.0,"LoadNumber":6}
]}

 

1、定义一个视图

直到现在,大家的运用唯有很少代码,唯有七个文 件 app.js 和
app/controller/Students.js,现在大家想扩张一个grid突显所有系统中的学生列表,修改3处:

1.5 运行图

882828九五至尊手机版 3

 

(1)、添加view/List.js视图

是时候更好的团体一下逻辑并伊始选用视图了。

视图也是组件,平常都是ExtJS现有组件的子类,现在准备开创学生表,先创造
app/view/student/List.js ,添加代码:

Ext.define('FWY.view.student.List' ,{
    extend: 'Ext.grid.Panel',
    alias : 'widget.studentlist',
    title : '学生信息列表',
    initComponent: function() {
        this.store = {
            fields: ['id','name', 'age','sex'],
            data  : [
                {id:1,name: 'zhangsan',    age: 18,sex:'boy'},
                {id:2,name: 'lishi',    age: 20,sex:'girl'}
        ]};
        this.columns = [
            {header: '编号',  dataIndex: 'id',  flex: 1},
            {header: '姓名',  dataIndex: 'name',  flex: 1},
            {header: '年龄', dataIndex: 'age', flex: 1},
            {header: '性别', dataIndex: 'sex', flex: 1}
        ];
        this.callParent(arguments);
    }
});

2. 数据查询

询问功能比较简单,只需求shipMgrStore在每一次请求时增大上询问条件。

(2)、修改controller/Students.js

我们的视图类就是一个普普通通的类,那个事例中咱们增加了 Grid
组件,并设置了别名,那样我们可以用 xtype
的方法调用这一个组件,其它大家也添加了 store 和 columns 的布置。
接下来大家需求充分那个视图到 Students控制器。因为大家用
‘widget.studentlist’ 设置了别名,所以大家能够使用 studentlist
作为xtype,就好像大家选拔以前运用的 ‘panel’

Ext.define('FWY.controller.Students', {
    extend: 'Ext.app.Controller',
    views: [
        'student.List'//添加view视图
    ],
    init: ...
    onPanelRendered: ...
});

2.1 成立一个搜索框

率先在shipMgrGrid的上方工具栏处创设一个文本输入框和一个询问按钮。

点击查询按钮,会触发shipMgrStore.loadPage(1)事件:

// 创建工具条
var shipMgrToolBarPanel = Ext.create('Ext.panel.Panel', {
    width: '100%',
    height: 40,
    bodyBorder: false,
    border: false,
    region: 'north',
    tbar: [
        Ext.create('Ext.form.field.Text', {
            name: 'SearchTxt',
            emptyText: '请输入船舶名称',
            width: 200,
            enableKeyEvents: true,
            listeners: {
                keyup: function (thisControl, e, eOpts) {
                    if (e.button == 12) {  // 若敲的键为回车,就执行【查询】搜索
                        shipMgrToolBarPanel.down('[name=QueryBtn]').handler();
                    }
                }
            }
        }),
        Ext.create('Ext.Action', {
            icon: 'Resources/icon/find.png',
            text: '查询',
            name: 'QueryBtn',
            handler: function () {
                // 设置搜索条件
                searchConditionObj.SearchTxt = shipMgrToolBarPanel.down('[name=SearchTxt]').value;
                shipMgrStore.loadPage(1);
            }
        })
    ]
});

 

(3)、修改app.js,加载视图

接下去修改 app.js 让视图在viewport中渲染,要求修改 launch 方法

Ext.application({
    ...
    launch: function() {
        Ext.create('Ext.container.Viewport', {
            layout: 'fit',
            items: {
                xtype: 'studentlist'
            }
        });
    }
});

唯一需求留意的是我们在views数组中指定了 ‘student.List’
,那告诉应用去自动加载对应的公文,ExtJS4
的动态加载系统会按照规则从服务器自动拉取文件,例如student.List就是平整,把.替换成/就是文本存放路径。刷新一下页面即可见到效果

2.2. store附加搜索条件

shipMgrStore每便请求时都增大搜索条件:

// 创建store
var shipMgrStore = Ext.create('Ext.data.Store', {
    model: 'App.ShipMgr.model.ShipModel',
    pageSize: 25,
    autoLoad: true,
    proxy: {
        type: 'ajax',
        url: '/Business/ShipMgr/Query',
        reader: {
            reader: 'json',
            root: 'data',
            totalProperty: 'rowCount',
        },
        actionMethods: {
            create: 'Post'
        }
    },
    listeners: {
        beforeload: function (thisStore, record, opts) {
            // 附加检索条件
            thisStore.proxy.extraParams = searchConditionObj;
        }
    }
});

 

 

2、添加对列表的控制

分三步成功对对编辑窗体的支配

2.3 运行图

882828九五至尊手机版 4

 

(1)、为grid绑定双击事件

小心 onPanelRendered 方法照旧被调用,因为我们的grid依然满足 ‘viewport
> panel’ 选用器,因为我们的视图继承自 Grid ,从而继续自
Panel。现在我们需求紧密一下选拔器,大家采用xtype作为采用器替换此前的
‘viewport > panel’ ,监听双击事件,以便继续做编辑用户消息:

Ext.define('FWY.controller.Students', {
    extend: 'Ext.app.Controller',
    views: [    
        'student.List'
    ],
    init: function() {
        this.control({
            'studentlist': {
                itemdblclick: this. editStudent//添加行双击事件
            }
        });
    },
    editStudent: function(grid, record) {
        console.log('Double clicked on ' + record.get('name'));
    }
});

留神我们转移了组件查询接纳器为 ‘studentlist’ ,监听的轩然大波改变为
‘itemdblclick’ ,响应函数设置为
editStudent,现在只是简单的日志出双击行的name属性。

3. 在线演示

在线演示http://www.akmsg.com/ExtJS/index.html#App.ShipMgr.ShipMgrTab

 

End

Web开发之路体系作品

食谱加载中…

(2)、创建view/student/Edit.js视图

可以见见日志是不利的,但大家实际上想做的是编辑用户音信,让大家现在做,创设一个新的视图
app/view/student/Edit.js

Ext.define('FWY.view.student.Edit', {
    extend: 'Ext.window.Window',
    alias : 'widget.studentedit',
    title : '修改学生信息',
    layout: 'fit',
    autoShow: true,
    initComponent: function() {
        this.items = [
            {
                xtype: 'form',
                items: [
                    {
                        xtype: 'textfield',
                        name : 'name',
                        fieldLabel: '姓名'
                    },
                    {
                        xtype: 'textfield',
                        name : 'age',
                        fieldLabel: '年龄'
                    },
                    {
                        xtype: 'textfield',
                        name : 'sex',
                        fieldLabel: '性别'
                    }
                ]
            }
        ];
        this.buttons = [
            {
                text: '保存',
                action: 'save'
            },
            {
                text: '取消',
                scope: this,
                handler: this.close
            }
        ];

        this.callParent(arguments);
    }
});
(3)、修改控制器加载视图

接下去我们要做的就是在控制器加载这些视图,渲染并且加载用户音信:

Ext.define('FWY.controller.Students', {
    extend: 'Ext.app.Controller',
    views: [
        'student.List',
        'student.Edit'//添加edit视图
    ],
    init: ...
    editStudent: function(grid, record) {
        var view = Ext.widget('studentedit');//注册组件,显示窗口
        view.down('form').loadRecord(record);//加载数据到表单中
    }
});

首先大家用 Ext.widget 方法成立了视图,那么些法子一致
Ext.create('widget.studentedit'),然后大家又三次借助组件查询找到了窗口中的表单,每个ExtJS4中的组件都有一个
down办法,可以凭借组件查询援救的选拔器来迅速找到任意下层的机件,双击表格中的一行可以看来弹窗效果。

3、创设Store和Model进行重构

现在我们有了表单,可以起来编制和封存用户新闻了,可是那前边须求做一点点重构。
FWY.view.student.List 创设了一个内联的 Store
,那样可以干活只是大家必要把 Store
分离出来以便大家在选用的其他职位可以引用并更新其中的音信,大家把它放在它应该在的文本中
app/store/Students.js

Ext.define('FWY.store.Students', {
    extend: 'Ext.data.Store',
    fields: ['id','name', 'age','sex'],
    data: [
        {id:1,name: '张三',    age: 30,sex:'男'},
        {id:2,name: '李四',    age: 20,sex:'女'}
    ]
});

现在大家需求做两处改动,首先大家须要让 Students 开端化的时候加载那一个Store :

Ext.define('FWY.controller.Students', {
    extend: 'Ext.app.Controller',
    stores: ['Students'],//加载store
    ...
});

接下来大家要把以前平昔在视图中内联的store更改掉,

Ext.define('FWY.view.student.List' ,{
    extend: 'Ext.grid.Panel',
    alias : 'widget.studentlist',
    store: 'Students',//引用Store
    ...
});

控制器的代码中中引入了store,store会被机关加载到页面并赋予一个storeId,这让视图中拔取store变的不难(这几个例子中,只要配置
store: ‘Students’ 就可以了) 现在大家只是在store中内联的概念了七个字段
(id,name,age,sex),那样可以干活了。

进一步重构:

ExtJS4中有一个无敌的
Ext.data.Model类,在编辑用户的时候大家得以看重它,使用Model重构下Store,在
app/model/Student.js中创制一个Model:

Ext.define('FWY.model.Student', {
    extend: 'Ext.data.Model',
    fields: ['id','name','age','sex']
});

那就是概念我们的Model须要做的,现在亟需让Store引用Model替换掉使用内联字段的艺术,并且让控制器也引用Model:

//修改控制器,引用Model
Ext.define('FWY.controller.Students', {
    extend: 'Ext.app.Controller',
    stores: ['Students'],
    models: ['Student'],
    ...
});
//修改store,引用Model
Ext.define('FWY.store.Students', {
    extend: 'Ext.data.Store',
    model: 'FWY.model.Student',
    data: [
        {id:1,name: '张三1',    age: 30,sex:'男'},
        {id:2,name: '李四1',    age: 21,sex:'女'}
    ]
});

4、利用模型保存数据

当今大家有了一个用户数据表,双击每⼀一行都能开拓一个编纂窗口,现在要做的是保留编辑变更,编辑窗口有一个编制表单,还有保存按钮,现在我们立异一下控制器让保存按钮有响应:

Ext.define('FWY.controller.Students', {
    init: function() {
        this.control({
            'viewport > studentlist': {
                itemdblclick: this.editStudent
            },
            'studentedit button[action=save]': {//获取studentedit视图中的button配置action=‘save’的按钮事件
                click: this.updateStudent
            }
        });
    },
    updateStudent: function(button) {
        console.log('clicked the Save button');
    }
});    

接下去填充 updateStudent 真正的逻辑。大家须求把数据从表单中取出,再
设置回store中:

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

5、保存到服务器

让大家扩充和服务器端的并行完结那些事例。现在我们仍然应编码了两行表格的数
据,现在让大家通过ajax加载:

Ext.define('FWY.store.Students', {
    extend: 'Ext.data.Store',
    model: 'FWY.model.Student',
    autoLoad: true,
    proxy: {
        type: 'ajax',
        url: 'data/students.json',
        reader: {
            type: 'json',
            root: 'students',
            successProperty: 'success'
        }
    }
});

此间大家去除了 ‘data’ 属性,替换成 proxy
,代理是让Store或者Model加载和保存数据的一个艺术,有AJAX,JSONP,HTML5的localStorage本地存储等。那里大家采纳了一个简约的AJAX代理,让它通过URL
‘data/students.json’ 加载数据。

大家还要给代理附加了一个reader,reader是用来把服务器重返的数码解码成Store能领会的格式,这一次大家应用了JSON
reader,并且指定了root和 successProperty 配置(JSON
reader的详细布署看文档),最终我们成立一下数据文件 data/students.json
,输入内容:

{
    success: true,
    users: [
        {id: 1, name: 'zhang',    email: 'zhang@126.com'},
        {id: 2, name: 'lishi', email: 'lishi@126.com'}
  ]
}

其它的转移就是我们给Store设置了 autoLoad 属性并安装为 true
,那意味Store生成之后会自动让Proxy加载数据,刷新⼀一下页面应该是观望和事先同一的结果,区其余是后天不是在先后中存在硬编码数据了,最终的事情是将转移传回服务器端,这么些例子中大家拔取静态的JSON文件,没有运用数据库,但丰裕表达大家例子的了,首先做一点点生成报告proxy用于更新的url:

proxy: {
    type: 'ajax',
    api: {
        read: 'data/students.json',
        update: 'data/updateStudents.json',
    },
    reader: {
        type: 'json',
        root: 'students',
        successProperty: 'success'
    }
}

一如既往从 students.json 读取数据,可是变更会发送到 updateStudents.json
,那里我们做⼀个模拟的答复回包以让我们清楚程序可以正确工作,
updateStudents.json
只需求包罗{"success":true},其余要做的就是让Store在编制之后展开联合,须要在
updateStudent 函数中扩张一行代码:

    updateStudent: function(button) {
    var win    = button.up('window'),
    form   = win.down('form'),
    record = form.getRecord(),
    values = form.getValues();
    record.set(values);
    win.close();
    this.getStudentsStore().sync();//将数据同步到store中
}

最终附上本篇的代码:点击下载

–本篇完–

相关文章

Your Comments

近期评论

    功能


    网站地图xml地图