在JS的开发过程当中,大规模的JS脚本难以组织和维护,这一直是困扰前端开发人员的头等问题。Extjs为了解决这种问题,在Extjs 4.x版本中引入了MVC开发模式,开始将一个JS(Extjs)应用程序分割成Model-View-Controller三层,为JS应用程序的如何组织代码指明了方向,同时使得大规模JS代码变得更加易于重用和维护;这就是Extjs MVC开发模式的初衷。html
在官方给出的MVC例子中,咱们能够看到一个简单的列表编辑功能,这篇文章就围绕这个功能进行详细的讲解,让咱们一块儿来揭开Extjs MVC的神秘面纱!前端
本文的示例代码适用于Extjs 4.x和Extjs 5.x,在Extjs 4.2.1 和Extjs 5.0.1中亲测可用!mvc
咱们先来看一下这个例子,它的功能很是简单:在页面打开的时候加载一个列表,当双击列表中一行数据的时候打开编辑窗口,编辑完成以后点击保存按钮,而后更新列表。截图以下:app
extjs-mvc-in-detailthis
在常规的开发模式下,要实现这个功能很是简单,代码以下:spa
Ext.onReady(function () { //1.定义Model Ext.define("MyApp.model.User", { extend: "Ext.data.Model", fields: [ { name: 'name', type: 'string' }, { name: 'age', type: 'int' }, { name: 'phone', type: 'string' } ] }); //2.建立store var store = Ext.create("Ext.data.Store", { model: "MyApp.model.User", data: [ { name: "Tom", age: 5, phone: "123456" }, { name: "Jerry", age: 3, phone: "654321" } ] }); //3.建立grid var viewport = Ext.create("Ext.container.Viewport", { layout: "fit", items: { xtype: "grid", model: "MyApp.model.User", store: store, columns: [ { text: '姓名', dataIndex: 'name' }, { text: '年龄', dataIndex: 'age', xtype: 'numbercolumn', format: '0' }, { text: '电话', dataIndex: 'phone' } ] } }); //4.添加双击编辑 var grid = viewport.down("grid"); grid.on("itemdblclick", function (me, record, item, index, e, eopts) { //5.建立编辑表单 var win = Ext.create("Ext.window.Window", { title: "编辑用户", width: 300, height: 200, layout: "fit", items: { xtype: "form", margin: 5, border: false, fieldDefaults: { labelAlign: 'left', labelWidth: 60 }, items: [ { xtype: "textfield", name: "name", fieldLabel: "姓名" }, { xtype: "numberfield", name: "age", fieldLabel: "年龄" }, { xtype: "textfield", name: "phone", fieldLabel: "电话" } ] }, buttons: [ { text: "保存", handler: function () { win.down("form").updateRecord(); record.commit(); win.close(); } } ] }); win.down("form").loadRecord(record); win.show(); }); });
在这段代码中,咱们用到了Model、Store、Grid,以及编辑的Window和Form。代码中已经给出了简单的注释,这不是今天重点要介绍的。code
假设你历来没有接触过Extjs MVC开发模式,可是你知道ASP.NET MVC、或者别的任何语言下的MVC开发模式,那么咱们来试想一下Extjs下的MVC该是什么样子?orm
好了,咱们暂时想到了这么多,那么在实际的Extjs MVC开发过程当中是什么样子呢?咱们来看一下目录结构:htm
建立一个html页面,咱们使用mvc.html页面,在这个页面的同一个目录,咱们建立一个app的文件夹,在这个文件夹下面用来放置js代码。mvc.html就是咱们的程序宿主页面。对象
在app文件夹下面建立controller、model、store和view文件夹,从名称上就知道他们该放置什么代码了吧。而后建立Application.js做为咱们程序的入口文件,并在mvc.html中引用Application.js文件。
在model文件夹下面,建立user.js文件:
这个文件将存放咱们的model,咱们能够直接把最上面定义model的代码赋值到这里面。
app/model/User.js 的代码以下:
Ext.define('MyApp.model.User', { extend: 'Ext.data.Model', fields: [ { name: 'name', type: 'string' }, { name: 'age', type: 'int' }, { name: 'phone', type: 'string' } ] });
虽然store不是mvc中必须的步骤,可是做为数据仓库,store起到了数据存取的做用,grid、form等展示的数据都是经过store来提供的,所以store在extjs mvc开发模式中是必不可少的。
app/store/user.js 的代码以下:
Ext.define("MyApp.store.User", { extend: "Ext.data.Store", model: "MyApp.model.User", data: [ { name: "Tom", age: 5, phone: "123456" }, { name: "Jerry", age: 3, phone: "654321" } ] });
为了实现列表和编辑功能,咱们须要两个视图,分别是list和edit,那么view的结构以下:
app/view/user/List.js 对应咱们的grid的定义,只不过将建立grid的实例改为了建立grid的扩展。
app/view/user/List.js 代码以下:
Ext.define("MyApp.view.user.List", { extend: "Ext.grid.Panel", alias: 'widget.userlist', store: "User", initComponent: function () { this.columns = [ { text: '姓名', dataIndex: 'name' }, { text: '年龄', dataIndex: 'age', xtype: 'numbercolumn', format: '0' }, { text: '电话', dataIndex: 'phone' } ]; this.callParent(arguments); } });
app/view/user/edit.js 对应咱们的window的定义,但一样是经过扩展的形式来实现的。
app/view/user/edit.js 代码以下:
Ext.define("MyApp.view.user.Edit", { extend: "Ext.window.Window", alias: "widget.useredit", title: "编辑用户", width: 300, height: 200, layout: "fit", items: { xtype: "form", margin: 5, border: false, fieldDefaults: { labelAlign: 'left', labelWidth: 60 }, items: [ { xtype: "textfield", name: "name", fieldLabel: "姓名" }, { xtype: "numberfield", name: "age", fieldLabel: "年龄" }, { xtype: "textfield", name: "phone", fieldLabel: "电话" } ] }, buttons: [ { text: "保存", action: "save" } ] });
注意:对于view类的建立,咱们须要定义alias,这是为了方便咱们经过xtype来建立该组件的实例。(若是没有alias,咱们将很难在viewport和controller中使用 —— 这是我爬过的坑!)
controller做为链接model、store和view的桥梁,在mvc开发模式中起到了相当重要的做用。若是说model定义了数据模式、store提供了数据存取的方法、view用来展现数据,那么controller将用来控制具体的数据操做。
app/controller/user.js 的代码以下:
Ext.define('MyApp.controller.User', { extend: 'Ext.app.Controller', stores: ['User'], models: ['User'], views: ['Viewport', 'user.List', 'user.Edit'], init: function () { this.control({ 'userlist': { itemdblclick: this.editUser }, 'useredit button[action=save]': { click: this.saveUser } }); }, editUser: function (grid, record) { var win = Ext.widget("useredit"); win.down("form").loadRecord(record); win.show(); }, saveUser: function (btn) { var win = btn.up("window"), form = win.down("form"), record = form.getRecord(); form.updateRecord(); record.commit(); win.close(); } });
咱们来详细的说一下controller的这段代码。在这段代码中:
有了这些步骤,咱们就将model、store、view联系在一块儿了。而后,咱们进入Application.js文件中,完善咱们的入口页面。
在不少时候,Application.js文件也被简单的命名为app.js,它们的做用是同样的,为应用程序提供一个入口。它能够很简单,咱们的Application.js文件代码以下:
Ext.application({ name: "MyApp", appFolder: 'app', controllers: ["User"], autoCreateViewport: true, launch: function () { // 页面加载完成以后执行 } });
Viewport做为咱们应用程序的视图面板,能够被单独的定义在一个Viewport.js文件中。它的定义也很简单,一般用来将一个或多个view做为它的子控件。
app/view/viewport.js 代码以下:
Ext.define("MyApp.view.Viewport", { extend: "Ext.container.Viewport", layout: "fit", items: { xtype:"userlist" } });
完成这些步骤以后,咱们能够运行mvc.html来查看效果。
Extjs MVC开发模式为咱们提供了一个完善的代码组织和维护的方向,它的出发点是好的,可是在实际的操做过程当中,咱们会发现这种模式过于繁琐,这多是因为咱们的示例太过于简单而形成的。
Extjs MVC的Model、Store、View、Controller各层的代码都是经过Ext.define来建立类的形式完成的,所以在使用Extjs MVC以前,咱们须要对Extjs的类系统有必定的认识,包括如何使用Ext.define自定义类。
对于View层的控件,咱们须要为它们指定一个alias属性,方便经过xtype建立对象,并能够在Controller中方便的找到他,为它的子控件添加具体的操做。