【翻译】在Ext JS应用程序中构建可维护的控制器
原文:Building Maintainable Controllers in Ext JS Apps
在eMortgage Logic公司,2011年底开始使用Ext JS 4。当时,还不知道如何正确编写Ext JS应用程序,但最后还是掌握了如何让应用程序实现所需的方法。不过,这并不意味着能很好的去实现他们。最终结果是,应用程序是由十几个大规模控制器实现处理的,而同时,视图使用的是一组简单的配置。控制器掌控着一切,但随着时间的推移,控制器变得越来越难于维护,这就让人开始怀疑当初的代码是否妥当了。
最后,我们试图让视图变得聪明一点,沿着这个思路,我们有点开窍了。最终,终于知道如何在控制器和视图之间划清界线了。为了说明我们团队新发现的这个知识,我撰写了以下这个指南。该指南使用了一个简单的方式来说明如何拆卸大的控制器并替换他们的的逻辑代码,以便于维护。这不仅有利于短期内使用Ext JS 4的团队,也有利于近期升级到Ext JS 5视图控制器的团队。
在这篇文章,将创建一个小型的控制和有几个需求的简单视图,然后通过几个步骤来分离他们。
本文最终的目标是创建一个实现以下要求的控制器和视图:
- 提供一个表单让用户输入喜好
- 保持喜好到用户的记录
- 更新用户的名字和喜好等信息
你好,“You Had Me”
创建的视图将允许当前用户去查看和更新他们的爱好,该视图将使用build方法,因此后续工作会很简单。
app/view/Hobby.js
Ext.define('Example.view.Hobby', {
extend: 'Ext.form.Panel',
alias: 'widget.hobbyview',
initComponent: function () {
var me = this;
me.items = me.buildItems();
me.callParent(arguments);
},
buildItems: function () {
return [
{
xtype: 'textfield',
name: 'FavoriteHobby'
},
{
xtype: 'button',
itemId: 'save',
text: 'Save'
},
{
xtype: 'component',
itemId: 'hobbyTpl',
tpl: '{Name}\'s favorite hobby is {FavoriteHobby}'
}
];
}
});
下面,将创建控制器来管理视图:
app/controller/Hobby.js
Ext.define('Example.controller.Hobby', {
extend: 'Ext.app.Controller',
init: function () {
this.control({
'hobbyview button#save': {
click: this.onSaveButtonClick
}
});
},
onSaveButtonClick: function (button) {
var form = button.up('form'),
values = form.getValues(),
user;
// We will assume the application provides a way to get the currently logged-in user.
user = this.getApplication().getCurrentUser();
user.set(values);
user.save();
form.down('#hobbyTpl').update({
Name: user.get('Name'),
FavoriteHobby: values.FavoriteHobby
});
}
});
尽管是一个非常简单的控制器,但它知道视图对它有意见。
控制器要知道:
视图有一个ItemId为save的按钮
按钮是表单的一个子组件
如何从视图的表单中获得值
表单有一个itemId为hobbyTpl的子组件,如何去更新它?
表单不知道用户这个概念
控制器的一切完全依赖于视图的保存按钮和视图自身的结构,这将导致控制器和视图必须紧密耦合,譬如,如果保存按钮在表单组件的之外,控制器就不得不重写。另外,如果itemId为hobbyTpl的组件被改变,控制器也需要进行相应的更改。视图中的任何微小变化都可能会令控制器出现问题。
你是Tearing Me Apart
现在,你可以已经意识到控制器的一些问题了,下面就来解决这些问题。首先是要让视图与用户关联。
app/view/Hobby.js
Ext.define('Example.view.Hobby', {
// ...
bindUser: function (record) {
this.userRecord = record;
},
getUser: function () {
return this.userRecord;
}
// ...
});
通过设置一些方法来关联用户,这样就可以很容易的调整视图方法而不需要修改控制器。通过这些附加项,就可以通过传递一个实例或稍后调用bindUser方法后让视图关注用户记录。这样,还可以获取绑定的用户,而控制器则无须了解太多。
接下来,要让控制器允许视图去管理用户记录并更新数据。
app/controller/Hobby.js
Ext.define('Example.controller.Hobby', {
// ...
onSaveButtonClick: function (button) {
var form = button.up('form'),
values = form.getValues(),
user = form.getUser();
user.set(values);
user.save();
form.down('#hobbyTpl').update({
Name: user.get('Name'),
FavoriteHobby: values.FavoriteHobby
});
}
});
很不错了,不过清单里还有一件事没做,那就是控制器还是要了解视图的结构,现在要做的就是让它更灵活。
下面更新一下清单:
控制器知道
- 视图有一个ItemId为save的按钮
- 按钮是表单的一个子组件
- 如何从视图的表单中获得值
- 表单有一个itemId为hobbyTpl的子组件,如何去更新它?
表单不知道用户这个概念
模板?We Don’t Need [to be aware of] No Stinkin的模板
视图一直很想知道为什么控制器不能专注于自己的商业逻辑,而这可通过移除模板的相关内容来让它少管点闲事。
视图希望它的模板在保存按钮被单击时被更新,为了实现这个目标,需要添加事件处理。
app/view/Hobby.js
Ext.define('Example.view.Hobby', {
// ...
onSaveClick: function () {
var me = this,
values = me.getValues(),
user = me.getUser();
me.down('#hobbyTpl').update({
Name: user.get('Name'),
FavoriteHobby: values.FavoriteHobby
});
},
buildItems: function () {
var me = this;
return [
{
xtype: 'textfield',
name: 'FavoriteHobby'
},
{
xtype: 'button',
itemId: 'save',
text: 'Save',
listeners: {
click: me.onSaveClick,
scope: me
}
},
{
xtype: 'component',
itemId: 'hobbyTpl',
tpl: '{Name}\'s favorite hobby is {FavoriteHobby}'
}
];
}
});
现在,视图将处理更多的视图事务,而控制器也可以更简单了。
app/controller/Hobby.js
Ext.define('Example.controller.Hobby', {
// ...
onSaveButtonClick: function (button) {
var form = button.up('form'),
values = form.getValues(),
user = form.getUser();
user.set(values);
user.save();
}
});
不幸的是,控制器还是能看到不少的视图组件,不过至少列表中的事情又少了一件:
控制器知道
- 视图有一个ItemId为save的按钮
- 按钮是表单的一个子组件
- 如何从视图的表单中获得值
表单有一个itemId为hobbyTpl的子组件,如何去更新它?表单不知道用户这个概念
What We’ve Got Here是一个失败的沟通者
现在一举解决余下的问题的时候了,这需要通过事件来实现视图与控制器之间的沟通。控制器只需要知道视图要获取数据,并且需要保存数据。
在onSaveClick事件中,视图中已经聚集了控制器所需的所有数据,因此这里只需要从这里出发一个事件。
app/view/Hobby.js
Ext.define('Example.view.Hobby', {
// ...
onSaveClick: function () {
var me = this,
values = me.getValues(),
user = me.getUser();
me.fireEvent('save', me, values, user);
me.down('#hobbyTpl').update({
Name: user.get('Name'),
FavoriteHobby: values.FavoriteHobby
});
},
// ...
});
这小小的改变就可以让控制器变得足够简单,它只需要知道视图的存在,并会触发一个save事件。
app/controller/Hobby.js
Ext.define('Example.controller.Hobby', {
extend: 'Ext.app.Controller',
init: function () {
this.control({
'hobbyview': {
save: this.onSave
}
});
},
onSave: function (view, values, user) {
user.set(values);
user.save();
}
});
现在,控制器终于不需要再了解视图的结构了。控制器只保存数据,而是他只显示数据。
只要视图一直保持触发save时间,现在就不需要大量修改控制器了。
控制器知道
视图有一个ItemId为save的按钮按钮是表单的一个子组件如何从视图的表单中获得值表单有一个itemId为hobbyTpl的子组件,如何去更新它?表单不知道用户这个概念
聪明的视图是重点且易于维护和测试
了解如何拆卸猛犸级的控制器对于团队更好的管理类来说是相当有帮助的。不但是控制器,视图也变得更集中和易于维护,他们也易于测试,而这也更接近于Ext JS视图控制器的功能。让视图变得更聪明还便于应用程序重用他们。
要知道的是:
- 视图完全有能力管理自己的数据
- 控制器应该以不了解视图内部结构为前提
- 自定义事件是处理视图于控制器之间通信的最完美方式
作者:John Krull
John is a Software Engineer at eMortgage Logic. He has experience in web app development, agile software dev, and UI/UX design. He sp*ecializes in Ext JS, JavaScript, PHP, Perl, MySQL, HTML, and CSS.
【翻译】在Ext JS应用程序中构建可维护的控制器的更多相关文章
- 【翻译】在Ext JS应用程序中使用自定义图标
原文:Using Custom Icons in Your Ext JS App 作者:Lee BoonstraLee is a technical trainer at Sencha. She's ...
- 【翻译】Ext JS 6.2 早期访问版本发布
原文:Announcing Ext JS 6.2 Early Access 非常开心,Sencha Ext JS 6.2早期访问版本今天发布了.早期访问版本的主要目的是为了让大家进行测试并评估Ext ...
- 【翻译】Ext JS 6早期访问版本发布
早期访问版本是什么 如何参与 都包括什么 Sencha Ext JS 6 Sencha Pivot Grid Sencha Cmd 6 JetBrains IDE插件 反馈 原文:Announcing ...
- 【翻译】Ext JS 6有什么新东西?
工具包ToolKits 发布 包的命名 Fashion 图表 ItemEdit插件 网格 电子表格 可操作模式Actionable Mode和可访问性 LazyItems插件 屏幕阅读器支持可访问性 ...
- 【翻译】Ext JS最新技巧——2016-3-4
原文:Top Support Tips Kevin Cassidy:Grid水印 Ext JS的Grid是一个便于在布局中显示信息的伟大工具.有些用户可能会希望将这些信息打印为会议资料或宣传材料,而且 ...
- 【翻译】Ext JS最新技巧——2015-10-21
原文:Top Support Tips Kevin Cassidy:全宽度的字段错误信息 有考虑过让验证信息显示在表单字段的下面(msgTarget:'under'),但最后发现验证信息被压缩显示了吗 ...
- 【翻译】Ext JS最新技巧——2015-8-11
原文:Top Support Tips Seth Lemmons:使用棒极了的Awesome Font Ext JS 6附带了一个新的海卫一主题,可以使用Font Awesome字体作为背景图像的图标 ...
- 【翻译】Ext JS 6 Beta发布
原文:Ext JS 6 Beta is Now Available 概述 Ext JS 6的好处 新的Ext JS功能和工具 需要你的反馈意见 概述 很高兴,Ext JS 6 beta版本现在发布了. ...
- 【翻译】Ext JS——高效的编码风格指南
原文:ExtJS - Efficient coding style guide 作者:Raja 切勿使用"new"关键字:在Ext JS中,使用"new"关键字 ...
随机推荐
- 软件测试assert
之前实习做过一段时间测试,现做个总结: 实习测试的是一款CM系统(case 系统),来记录IT部门处理的维修,服务,反馈,预定服务等case:b/s架构,人少小项目,实习时间短,去了已经快完工,主要测 ...
- 数据结构之并查集Union-Find Sets
1. 概述 并查集(Disjoint set或者Union-find set)是一种树型的数据结构,常用于处理一些不相交集合(Disjoint Sets)的合并及查询问题. 2. 基本操作 并查集 ...
- 关于一些基础的Java问题的解答(四)
16. Java面向对象的三个特征与含义 java中的面向对象的三大基本特征分别是:封装.继承.多态: 封装:把过程和数据包围起来,对数据的访问只能通过已定义的界面,主要是方便类的修改 继承:对象的一 ...
- react 或 vue 中引用 jQuery 插件
前言 今天与遇到一个令人抓狂的事情, 因为项目中有个交互太过于复杂而且冷门, 没有人封装类似react-swiper那种的移植过来的插件 只有现成的jQuery插件. 而时间并不宽裕,自己重写成rea ...
- Java并发中的CopyOnWrite容器
Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改, ...
- Promise--优雅的异步回调解决方案
当一个接口需要依赖另一个接口的请求数据时,通常有两种解决方式,一个是将请求数据的接口设为同步,之后调另一个接口,另一个是在请求数据接口的成功回调里调另一个接口. 但是:当一个接口需要依赖很多个接口的请 ...
- 基于Python预测股价
▌实现预测的Stocker工具 Stocker是一款用于探索股票情况的Python工具.一旦我们安装了所需的库(查看文档),我们可以在脚本的同一文件夹中启动一个Jupyter Notebook,并导入 ...
- GDAL打开mdb文件失败解决方法
使用GDAL打开mdb文件时提示下面错误信息: ERROR 1: Unable to initialize ODBC connection to DSN for DRIVER=Microsoft Ac ...
- [CSDN_Markdown]使用LaTeX基本数学公式
简介 以前我很头疼在博文里写公式,一直期盼CSDN的博文编辑器能支持LaTeX 公式输入,今天终于可以使用这个功能了!此文主要讨论如何在CSDN的Markdown编辑器中写 LaTeX 公式! 使用L ...
- Swift基础之两指拉动图片变大变小
我们在使用APP的时候,有时会发现有些图片可以通过两指进行放大.缩小,今天就实现这样的一种效果,比较简单,不喜勿喷.... var imageVi:UIImageView! = nil var ...