我们正在尝试构建一个简单的原型来使用 ExtJs 使用我们的数据服务(同时也学习 ExtJs)。
在开发原型时(具备 ExtJS 的基本知识),我遇到了一些问题。在我发布问题之前,我想让您快速浏览一下以下内容。
以下是与服务交互的主要类。我们希望确保某些 UI 组件在 ajax 通信期间被屏蔽/取消屏蔽。
Ext.define('Sample.provider.SvcClient', {
TestConnectivity: function(prms){
debugger;
Ext.Ajax.on('beforerequest', function(conn,o,result) {
prms.BeforeRequest(conn,o,result);
});
Ext.Ajax.on('requestcomplete',function(conn,o,result) {
prms.RequestComplete(conn,o,result);
});
Ext.Ajax.on('requestexception',function(conn,o,result) {
prms.RequestException(conn,o,result);
});
Ext.Ajax.request({
url: prms.Url,
method: prms.HttpMethod,
headers: {
'Authorization' : 'Basic ' + prms.Credentials
},
success: prms.Success,
failure: prms.Failure,
callback: prms.Callback
});
}
});
我们为 SvcClient 开发了一个扩展,特别是为了帮助在 ajax 通信期间屏蔽控件:
Ext.define('Sample.util.ClientProxy', {
CtlToMask : null,
DoTestConnection: function(ctlToMask, callback, url, userName, pwd) {
debugger;
var proxy = this;
proxy.CtlToMask = ctlToMask;
var client = new Sample.provider.SvcClient();
var params = {
Url: url,
HttpMethod: "GET",
Credentials: Sample.util.Conversions.Base64.encode(userName + ":" + pwd),
CtlToMask: proxy.CtlToMask,
Scope:proxy,
BeforeRequest: function(conn,o,result,Scope) {
debugger;
if(Scope.CtlToMask !=null) {
if(Scope.CtlToMask.getEl() != undefined)
Scope.CtlToMask.getEl().mask('Testing Connectivity...', 'x-mask-loading');
else
Scope.CtlToMask.mask('Testing Connectivity...', 'x-mask-loading');
}
},
RequestComplete: function(conn,o,result) {
if(this.CtlToMask !=null) {
if(this.CtlToMask.getEl() != undefined)
this.CtlToMask.getEl().unmask(true);
else
this.CtlToMask.unmask(true);
}
},
RequestException: function(conn,o,result) {
if(this.CtlToMask !=null) {
if(this.CtlToMask.getEl() != undefined)
this.CtlToMask.getEl().unmask(true);
else
this.CtlToMask.unmask(true);
}
}
};
client.TestConnectivity(params);
}
});
我有如下所示的控制器:
Ext.define('Sample.controller.Locations', {
extend: 'Ext.app.Controller',
models: ['Location', 'Country'],
views: [
'portal.location.Menu',
'portal.location.Edit'
],
init: function() {
this.control({
'locationsMenu':{
OpenAddNewSvcPopup: this.OnOpenAddNewSvcPopup
},
'locationsEdit':{
TestSvcConnectivity: this.OnTestSvcConnectivity,
render: function () { },
afterrender: function () { },
boxready: function () { }
}
});
},
OnOpenAddNewSvcPopup: function(){
var newLoc = Ext.create('Sample.model.Location', {
UserName: 'admin',
Uri: 'http://localhost/DataServicesBase/Data.svc'
});
var v = Ext.create('widget.locationsEdit',{ mode:'add'});
v.down('form').loadRecord(newLoc);
},
OnTestSvcConnectivity: function(ctl){
var proxy = new Sample.util.ClientProxy();
proxy.DoTestConnection(
ctl,
this.OnTestSvcConnectivityCallback,
ctl.down("#Uri").value + '/Countries',
ctl.down("#UserName").value,
ctl.down("#Password").value
);
},
OnTestSvcConnectivityCallback: function(options,success,result){
if(success) {
//show the result
}
else {
//Show error in window
}
}
});
该视图如下所示:
Ext.define('Sample.view.portal.location.Edit', {
extend: 'Ext.window.Window',
alias: 'widget.locationsEdit',
//title: 'Edit Service Location',
layout: 'fit',
autoShow: true,
title: 'Edit Service Location',
bodyStyle: 'border:0px',
closeAction:'destroy',
config:{
mode: 'edit'
},
constructor: function(configs){
this.callParent(arguments);
this.initConfig(configs);
if(this.mode == "add") this.setTitle('Add New Service Location');
},
initComponent: function() {
this.items = [
{
xtype: 'form',
items: [
{
xtype: 'textfield',
name: 'Id',
itemId: 'Id',
fieldLabel: 'Unique Name',
labelStyle: 'font-weight:bold',
allowBlank: false,
maxLength: 64,
width: 300
},
{
xtype: 'textfield',
name : 'Uri',
itemId: 'Uri',
fieldLabel: 'URI',
maxLength: 300,
width: 500,
allowBlank: false
},
{
xtype: 'textfield',
name : 'UserName',
itemId: 'UserName',
fieldLabel: 'User Name',
allowBlank: false,
maxLength: 64,
width: 200
},
{
xtype: 'textfield',
name : 'Password',
itemId: 'Password',
fieldLabel: 'Password',
allowBlank: false,
maxLength: 64,
width: 200
}
],
bodyStyle: 'padding:5px;'
}
];
this.buttons = [
{
text: 'Test Connectivity',
action: 'test',
scope: this,
handler: this.OnTestSvcConnectivity
},
{
text: 'Save',
action: 'save'
},
{
text: 'Cancel',
scope: this,
handler: this.close
}
];
this.callParent();
this.addEvents('TestSvcConnectivity') //custom event
},
OnTestSvcConnectivity: function(){
this.fireEvent('TestSvcConnectivity', this); //will be raised to controller
}
});
第一季度
当我第一次单击“测试连接”按钮(从弹出窗口中)时,该方法工作正常。如果我第二次单击同一个按钮,则 (BeforeRequest) 处理程序会触发两次。第三次单击,处理程序被触发三次。我的代码中有什么错误。
第二季度
如果我取消弹出窗口并再次单击“测试连接”,它将永远无法工作。处理程序仍然维护先前弹出实例的“某种”引用(或状态)。由于找不到,它会在对象成员上抛出“未定义”。我通过调试器确认了这一点,我可以看到前一个弹出实例的 id 而不是当前的。无论如何,处理程序总是试图尊重第一个实例化的弹出窗口。
第三季度
我们试图为这个示例原型遵循的模式是否存在任何陷阱/问题。我们正在尝试使用 ExtJS 的 MVC 功能进行开发,并确保我们使用标准和良好的模式/实践,这样我们就不会面临上述非常基本的问题。