在ext js中开发控制器时,是否建议使用模块模式?
我相信通过这样做,我们实现了以下目标:
1)抽象出使用中的框架。业务逻辑已实施 在模块中。模块不(至少不应该),知道任何事情 关于框架功能。
2)暴露依赖性。框架应该为模块提供 所需数据。模块应该只运用这些知识。
3)更容易进行单元测试。您的测试不依赖于框架 知识。您只测试业务场景。
模块模式在sencha教程中非常流行,Ext之前的版本中的示例是4.0,但我在最近的教程中找不到任何对它的引用。
有什么变化吗?我错过了什么吗? 你使用这种做法吗?
感谢您的输入
编辑:
以下是主/细节控制器的代码 它将选定的行加载到详细信息表单中,然后触发'mycustomevent' 如果表单中的数据无效,它还会阻止网格行选择。
我添加了两种代码变体
1)简单的ext js实现。
2)使用模型模式的相同实现。
=== Ext Js Controller ===
Ext.define('Patterns.controller.MoviesMasterDetail', {
extend : 'Ext.app.Controller',
views : ['Patterns.view.Movies',
'Patterns.view.Detail'],
refs : [{
ref : 'Detail',
selector : 'detail'
}
],
init : function () {
this.control({
'movies' : {
beforeselect : this.onBeforeSelect,
selectionchange : this.onMovieSelected
},
'detail' : {
'mycustomevent' : this.onMyCustomEventWithArgs
}
});
},
onMyCustomEventWithArgs: function(arg) {
alert(arg);
},
onBeforeSelect : function () {
var detailForm = this.getDetail().getForm(),
hasRecord = detailForm.getRecord() != null;
if(hasRecord) {
return detailForm.isValid();
}
return true;
},
onMovieSelected : function (thisSelectionModel, selected, eOpts) {
var detail = this.getDetail();
var detailForm = detail.getForm();
var rec = selected[0];
rec.data['descr'] = 'modified';
detailForm.loadRecord(selected[0]);
detail.fireMyEvent('from controller');
}
});
===具有模块模式的Ext Js控制器===
Ext.define('Patterns.controller.MoviesMasterDetailModule', {
extend : 'Ext.app.Controller',
views : ['Patterns.view.Movies',
'Patterns.view.Detail'],
refs : [{
ref : 'Detail',
selector : 'detail'
}
],
init : function () {
this.control({
'movies' : {
beforeselect : this.onBeforeSelect,
selectionchange : this.onMovieSelected
},
'detail' : {
'mycustomevent' : this.onMyCustomEventWithArgs
}
});
},
onMyCustomEventWithArgs: function(arg) {
alert(arg);
},
onBeforeSelect : function () {
var me = this,
detailForm = me.getDetail().getForm(),
formRecord = detailForm.getRecord();
module = new Module();
return module.onBeforeSelect(formRecord, detailForm.isValid, detailForm);
},
onMovieSelected : function (thisSelectionModel, selected, eOpts) {
var detail = this.getDetail();
var detailForm = this.getDetail().getForm(),
module = new Module()
recToLoad = selected[0];
var loadRecordTupple = {
fn: detailForm.loadRecord,
scope: detailForm
};
var fireEventTupple = {
fn: detail.fireMyEvent,
scope: detail
};
module.modifyRecord(recToLoad, loadRecordTupple, fireEventTupple );
}
});
===模块实施===
function Module()
{
var onBeforeSelect = function(selectedRecord, validationFunc, caller){
if(!selectedRecord){
return true;
}
return validationFunc.apply(caller);
};
var modifyRecord = function(dataToLoad, loadTupple, fireEventTupple, caller){
dataToLoad.data['descr'] = "modified";
loadTupple.fn.apply(loadTupple.scope, [dataToLoad]);
fireEventTupple.fn.apply(fireEventTupple.scope, ["from module"]);
}
this.onBeforeSelect = onBeforeSelect;
this.modifyRecord = modifyRecord;
}
答案 0 :(得分:2)
丹尼尔斯 你问: “在ext js中开发控制器时,是否建议使用模块模式?” 我的答案是完全的,是的。虽然,ExtJs并没有在我看过的任何地方的作品中提出它。
我在CO的Denver举行的Javascript Meetup上做了一个演示,展示了我编写的库的用法,该库强制执行Modular(构造函数驱动的)MVC设计模式。
该演示文稿是ExtJs Architect应用程序的主要开发人员之一。他告诉我(不记录)模块化MVC设计模式的使用是ExtJs的用武之地。所以也许我们会在ExtJs 5文档中看到这个设计模式。但截至今天,ExtJs仍然建议将所有控制器放在一个文件夹中,并将视图放在一个文件夹中,并将模型放在一个文件夹中并存储在....你得到它。在大型Web应用程序开发方面,您和我以及其他一些人所知道的将无法正常工作。
这变成了一个咆哮,让我切入追逐(我的同事注意到这篇文章并希望我分享一些见解): 模块化设计模式完全可以与ExtJs一起使用,并且它非常有效。在使用ExtJs Framework时,您只需编写自己的库来强制执行该模式。我正在使用自己的库,它有:
为了给出我的“咆哮”观点,我作为承包商($$$)开发了Web应用程序(SAAS和企业内部网应用程序)已有20年。在过去的20年里,我使用过YUI,DOJO,ExtJs,Backbone和其他一些人。我为DOJO,ExtJs& amp;编写了我的模块化MVC设计模式库的版本。 BackBone(也适用于ActionScript,但这是另一个故事)。
ExtJs有一个非常稳定的框架(如果你查看它们的源代码,你会看到编码风格的一些例外),它们适用于大多数设计模式。
那么,再次回答你原来的问题: “在ext js中开发控制器时,是否建议使用模块模式?” 我的答案是完全的,是的。
============= 最糟糕的Javascript建议,我一遍又一遍地听到: “为什么我们不在JQuery中全部完成”
对DanielS评论的回答:
DanielS,我为我的回复延迟而道歉,我会尽可能地为您提供步骤。在每件作品之后,请发一个问题(如果有的话),我们可以继续谈话。
我的方法是首先创建一个JSON Constructor对象,该对象将反映我的Web应用程序的布局(这是Web应用程序构造函数):
{
confiiguration: {
modules: [
{
"config": "modules/HelloWordlModule/config/helloWorldConfig.json"
"namespace": "Modules.HelloWorldModule.HelloWorld" // Namespace of the modules controller
}
]
}
}
然后我会创建一个类(这是库启动的地方),它将解析json对象,并通过nameSpace值Ext.require模块,然后在Ext.require语句的回调中,我将实例化模块将路径发送到模块配置文件(在“config”值中找到)作为构造函数参数(Ext.create(Modules.HelloWorldModule.HelloWorld,{configEndpoint:config});)。在实例化的Module的控制器中,我会发出一个ajax请求来获取模块的JSON配置(使用商店和模型来管理ajax请求)。
从模块发送事件时: 创建一个扩展Ext.app.Controller的单例类。使用该类的实例来触发事件。 例如:
Ext.define('Modules.EventsController.ModulesEvents', {
extend: 'Ext.app.Controller',
singleton: true,
/** @property */
LOGIN_USER: 'loginUser'
};
Ext.define('Modules.HelloWorldModule.HelloWorld',{
extend: 'Ext.app.Controller',
requires: [
"Modules.EventsController.ModulesEvents" // requiring singleton, instantiates the class
],
onUserLogin: function(){
var modulesEventBus = this.getModulesEventBus();
if(modulesEventBus){
modulesEventBus.fireEvent(modulesEventBus.LOGIN_USER, { username: 'jDoe', email: 'jdoe@website.com'});
}
},
getModulesEventBus: function(){
var eventBus = Modules.EventsController.ModulesEvents;
if(!eventBus){
console.log("eventBus is undefined");
}
return eventBus;
}
});
答案 1 :(得分:0)
丹尼尔斯 您添加的代码示例看起来像是一个很好的Web应用程序的良好开端,但我认为我对模块的定义与您在此处的定义不同。我的一个模块是:
那个模块可以是:
关于活动巴士。我通常使用3种类型的事件总线。
仅凭这一点并不是我创建自己的事件总线的原因。
所以这个:
this.eventBus.fireEvent("loginUser");
this.eventBus.on("loginUser");
变为
this.eventBus.fireEvent(this.eventBus.LOGIN_USER);
this.eventBus.on(this.eventBus.LOGIN_USER);