javascript代码实例教程-ExtJSMVCArchitecture

发布时间:2019-01-15 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了javascript代码实例教程-ExtJSMVCArchitecture脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
小宝典致力于为广大程序猿(媛)提供高品质的代码服务,请大家多多光顾小站,小宝典在此谢过。

ExtJSMVCArchITecture,我们之前在之前的 Ext JS Architecture介绍的Ext JS 6的应用程序的结构,简单介绍了MVC, 和MVVM两种体系,这里包括Controller, Model, View, ViewModel, ViewController等相关的知识。因为Ext JS 6中,同样支持MVC结构,而在之前的文章中,并没有详细的讲到MVC, 更多的是新特性MVVM结构,本指南将详细的讲解MVC, Ext JS 4只有此结构,所以在Ext JS 4的文档中找到此文章.

当前Ext JS 6中的Ext.app.Application中,关于application architecture的链接是错误的,它应该是此链接,在此纠正一下 https://docs.sencha.COM/extjs/4.1.3/#!/guide/application_architecture

MVC Architecture

大型的客户端程序都是很难写,难以组织和维护。随着功能和开发人员的增加,更加难以控制。Ext JS 4提供了一个新的应用程序架构,不仅能够更好的组织你的代码,还能减少代码量。

我们的应用程序架构遵循 MVC-like模式,首次引入了Controller和Models. 当前有许多的MVC结构,其中大部分的定义都有略微的不同,以下是我们对MVC的定义:

Model是多个字段(field)和他们数据的集合(e.g. 一个User model包含username 和 password field). Models知道如何通过data package进行执久化, 也能够通过association(关系)跟其它的model进行相连。Models的功能跟Ext JS 3中的Record class相同。并且跟Stores一起,用于grids和其它组件数据显示 View 任何组件类型 - grids, trees,panel都称之为view. Controllers 存放你的应用代码逻辑的地方,包括是否渲染视图,实例化Models, 或者其它的逻辑

在本指南中,我们将创建一个非常简单的应用,来管理用户数据。

应用程序架构主要是为实际的类和框架代码提供结构,并且保持代码的一致性,它有以下作用:

每个application的原理都是一致的,所以你只需要了解一遍,就能知道它的运行原理 更容易在不同的应用之前共享代码,因为它们的工作方式是一样的 你可以使用我们的编译工具,创建一个优化后的PRoduction版本

File Structure

Ext JS 4应用遵循统一的目录结构,在MVC结构中,所有的类都存放在app/目录下. 如下图所示

javascript代码实例教程-ExtJSMVCArchitecture

在这个例子中,我们将整个应程程序封装在’account_manager’目录中。 所需要的Ext JS 4 SDK文件,则保存在ext-4/目录下。因此index.htML文件的内容如下

 
<script tyPE="text/javascript" src="ext-4/ext-debug.js"></script><script type="text/javascript" src="app.js"></script>

Creating the application in app.js

Ext JS 应用通常是使用Ext.container.Viewport创建的单页面应用

一个应用由一个或者多个Views组件,一个view的行为由相应的Ext.app.ViewController和Ext.app.ViewModel进行管理。

每一个 Ext JS 4 application都是从 Applcation类的实例开始, Application类包含你应用的全局设置(比如app的name, 创建一个全局的命名空间), 还包含app中要使用到的其它类的引用,比如models, views, controllers. 一个Application还包含一个launch 函数, 它在整个页面都加载完成时,自动运行

让我们创建一个简单的Account Manager app,用来帮助我们管理用户帐号。首先我们需要为application选择一个namespace. 所有的Ext JS 4应用都应该使用单个的全局变量,这样,application中的所有类都在这个全局变量之下。
通常我们需要一个简短的全局变量,我们在这里使用 “AM”

 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'                 }             ]         });     } });

上面的代码做了以下几件事, 首先调用Ext.application创建一个新的Application实例,给这个实例传递的name ‘AM’. 它会为我们自动创建一个全局变量AM, 并且在Ext.Loader中注册这个namespace. 并且通过appFolder设置与namespace相应的文件夹路径。我们也简单的提供了一个launch函数,它仅创建一个 Viewport, Viewport创建好后,可以自动的渲染到doucment body。 一个页面,只能创建一个Viewport.

javascript代码实例教程-ExtJSMVCArchitecture

Defining a Controller

Controller相当于应用程序中的胶水,将应用程序中的元素(views, models)绑定到一起. 它真正做的是,监听事件(监听views中的事件),并做出相应的处理。接下来,我们创建一个app/controller/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 控制器添加到application配置中, 修改 app.js的以下代码:

 Ext.application({     ...      controllers: [         'Users'     ],      ... });

当我们在浏览器中查看index.html, Users controller会自动的被加载(因为我们在application中有指定它), 并且它的init函数在application的launch之前被调用.

init函数是设置你的控制器与view交互的一个好地方,在init函数中,经常使用this.control函数,用来监听view类的事件,并作出相应的行为。接下来,我们更新Users controller的代码,告诉我们,panel什么时候被渲染

 Ext.define("AM.controller.Users", {     extend: "Ext.app.Controller",     init: function(){         console.log("'Initialized Users! This happens before the Application launch function is called ")         this.control({             'viewport > panel': {  //use Ext.componentQuery class                 render: this.onPanelRendered             }         })     },     onPanelRendered: function(){         console.log('The panel was render');     } })

我们使用this.control来设置application中视图的监听器。control函数使用新的ComponentQuery 引擎来快速获取一个页面中组件的引用(xtype)。如果你还不熟悉ComponentQuery, 可以查看Component Query文档, 简单来说,它允许我们使用类似于CSS选择器,来匹配一个页面的组件(不是html节点, 而是Ext JS的Component, 可以是xtype, ID)

在我们的init函数中,我们使用了’viewport > panel’,它表示”viewport 下的直接Panel组件, 它返回一个数组,包含每个组件的引用”. 然后我们指定一个对像,对像中的键映射为匹配到组件的事件名称,它的值映射为每个事件的处理函数。即,为所有匹配到的组件,注册事件监听函数。

##Defining a View

接下来,我们想添加一个grid,用来显示我们系统中的users.

其实View就是一个组件,它是Ext JS Component的一个子类。我们创建一个app/view/user/List.js文件,使用一个grid来显示用户列表

 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);     } });

我们的View Class就是一个普通的类。在这里,我们让它继承于Grid 组件,并且设置它的别名,这样我们就可以用xtype的方式来使用它。我们也配置了一个store和columns, 这两个配置是grid渲染时,需要使用到的数据

接下来,我们将view添加到User controller中。 因为我们设置别名时,使用了特殊的’widget.’格式,所以可以使用’userlist’作为xtype. 类似于之前使用的’panel’

接下来,我们需要在Users controller中添加这个view, 否则没有办法在app.js中使用 xtype对它渲染。

 Ext.define('AM.controller.Users', {     extend: 'Ext.app.Controller',      views: [         'user.List'     ],      init: ...      onPanelRendered: ... });

然后,我们可以在main viewport中,对它进行浸染

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

需要注意的一个事件是,我们在views数组中,指定了’user.List’, 它是告诉应用程序自动加载这些文件,这样我们才能在application launch中使用这些组件。application使用了Ext JS 4中新的动态加载系统,可以自动从服务器上加载。

javascript代码实例教程-ExtJSMVCArchitecture

Controlling the grid

当前onPanelRendered函数依然可以执行,这是因为grid类 继承于 Panel类,符合’viewport > panel’选择器。

所以我们需要使用一个新的xtype,用来缩窄选择的范围。我们可以添加以下代码,用来监听grid中每一行的双击事件

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

效果如下图所示

javascript代码实例教程-ExtJSMVCArchitecture

接下来,我们创建一个app/view/user/Edit.js,用来真真的编辑用户信息,而不是简单的console log

 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);     } });

我们再次定义了已存在组件(这次为Ext.window.Window)的一个子类. 布局使用 ‘fit’,它适用于一个组件的容器,它的子组件,随着容器大小的改变而改变。

接下来,我们在controller中添加新创建的view. 并且渲染它

 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,来查找form 组件。每一个Component都有一个down函数,它接收一个ComponentQuery选择器,可以快迅的查找一个子组件。

javascript代码实例教程-ExtJSMVCArchitecture

Creating a Model and a Store

当前我们的是以内联的方法创建的store. 虽然这样也可以,但我们想要在应用程序的任何地方引用这个store, 并更新它的数据,那就需要将它提取出来,存放到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'}     ] });

然后修改controller,

 Ext.define('AM.controller.Users', {     extend: 'Ext.app.Controller',     stores: [         'Users'     ],     ... });

然后,我们就可以在app/view/user/List.js中,通过id来引用这个store.

 Ext.define('AM.view.user.List' ,{     extend: 'Ext.grid.Panel',     alias: 'widget.userlist',     title: 'All Users',      //我们不需要initComponent中定义User store.     store: 'Users',      initComponent: function() {          this.columns = [         ... });

我们在Users controller中包含stores,是用来告诉应用程序自动加载这个store文件,并且根据store类的定义,给定一个storeid, 这样就可以在view中,通过id引用相应的store.

当前我们只在store中定义了’name’和’email’字段。虽然这也可以满足我们的需求,但在Ext JS 4中,我们有一个更强大的Ext.data.Model类

 Ext.define('AM.model.User', {     extend: 'Ext.data.Model',     fields: ['name', 'email'] });

接下来,我们替换store中的内联field

 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'}     ] });

然后,我们也需要告诉User controller获得User model的引用

 Ext.define('AM.controller.Users', {     extend: 'Ext.app.Controller',     stores: ['Users'],     models: ['User'],     ... });

Saving data with the Model

首先让我们监听save button

 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');     }     ... });

现在我们可以看到,点击save后,将日志出输到控制台,接下来,我们更新User

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

Client 事件给了我们一个button的引用,但我们实际上是需要访问 form 组件(它包含数据) 和window 组件。所以我们再次使用了ComponentQuery,先通过button.up(‘window’)获得Edit User window, 然后通过win.down(‘form’)获得 form.

Saving to the server

 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’属性,而用 一个Proxy代替。 PROIxs可以用于store和model中,用来加载和保存数据,类型有AJAX, JSON-P 以及HTML5 localStorage. 在这里,我们使用 AJAX代理,加载服务器的’data/users.json’.

我们在代理中定义了一个Reader, 它用于解析服务器响应到Store可以理解的格式。这里,我们使用了JSON Reader, 并且指定了JSON中数据保存的位置root, 以及successProperty. 以下是
data/user.json文件

 {     "success": true,     "users": [         {"id": 1, "name": 'Ed',    "email": "ed@sencha.com"},         {"id": 2, "name": 'Tommy', "email": "tommy@sencha.com"}     ] }

在store中,我们还有一个autoLoad=true, 它的意思是Store将要求Proxy立即加载数据。如果我们刷新网页,将看到跟之前的效果是一样的。但现在我们却可以不用将数据硬编码在application。

接下来,我们需要将改变的数据返回到服务器。

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

我们依然从user.json中读取数据,但是任何的更新,都将发送到updateUser.json.

接下来,我们需要告诉Store 跟服务器同步

 updateUser: function(button) {     var win    = button.up('window'),         form   = win.down('form'),         record = form.getRecord(),         values = form.getValues();      record.set(values);     win.close();     // synchronize the store after editing the record     this.getUsersStore().sync(); }

觉得可用,就经常来吧! 脚本宝典 欢迎评论哦!&nbsp;js脚本,巧夺天工,精雕玉琢。小宝典献丑了!

脚本宝典总结

以上是脚本宝典为你收集整理的javascript代码实例教程-ExtJSMVCArchitecture全部内容,希望文章能够帮你解决javascript代码实例教程-ExtJSMVCArchitecture所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。