假设我有一个按钮可以触发新视图的推送。我注意到,如果我不止一次地点击它,足够快,它会推动同一个视图两次。
您可以使用他们在此页面上的官方文档来模仿这种行为,他们有一个实时示例: http ://docs.sencha.com/touch/2-0/#!/guide/navigation_view
明确的问题是,如何预防呢?
假设我有一个按钮可以触发新视图的推送。我注意到,如果我不止一次地点击它,足够快,它会推动同一个视图两次。
您可以使用他们在此页面上的官方文档来模仿这种行为,他们有一个实时示例: http ://docs.sencha.com/touch/2-0/#!/guide/navigation_view
明确的问题是,如何预防呢?
另一种方法是检查活动视图是什么,只有在它与您要推送的视图不同时才推送。我已经对此进行了测试,并且可以正常工作。
例如
if (this.getNavigationView().getActiveItem().xtype != "someView") {
this.getNavigationView().push({ xtype: "someView" });
}
扩展 jayteejee 的答案,我在自定义导航视图中覆盖了 push 方法,如下所示:
Ext.define('BT.navigation.View', {
extend: 'Ext.navigation.View',
xtype: 'btnavigationview',
push: function (view) {
if(this.getActiveItem().xtype != view.xtype)
this.callParent(arguments);
else
console.warn("Prevented pushing a potentially duplicate view of xtype: " + view.xtype);
}
});
我不完全确定xtype
假设是否足够安全,但我想不出在我当前的应用程序中需要一个视图将另一个相同类型的视图推送到导航堆栈的情况。因此,该解决方案对我有用,而且非常简洁。警告是为了让我以后头疼,可能会拉我的头发试图找出为什么push
不起作用!
掩蔽成功地防止了双击问题。
在我的代码中,我使用两个函数来屏蔽/取消屏蔽导航容器:
/**
* Mask container with rolling wheel. Usually need if Ajax-request is sent to the server and app waiting for response
* Best practice is masking the current navigator container, to prevent blocking whole app. Method warns if no container
* is defined. In some cases warning could be suppress with parameter
*
* @param container
* @param {boolean} [suppressWarning]
*/
startLoading: function(container, suppressWarning) {
var loadingComponent = container;
if (!loadingComponent) {
// <debug>
if (!suppressWarning) {
console.warn('Please define navigator container for non-blocking operation, or define suppressWarning parameter');
}
// </debug>
loadingComponent = Ext.Viewport;
}
// var lastMaskedContainer = container;
this.lastMaskedContainer = container;
loadingComponent.setMasked({
xtype: 'loadmask',
message: 'Loading...'
});
/*
Ext.defer(function() {
lastMaskedContainer.setMasked(false);
}, Pipedrive.app.maskingTimeout * 1000)
*/
},
/**
*
* @param {Ext.Container} container
* @param {boolean} [suppressWarning]
*/
stopLoading: function(container, suppressWarning) {
var loadingComponent = container;
if (!loadingComponent) {
// <debug>
if (!suppressWarning) {
console.warn('Please define either navigator container for non-blocking operation, or define suppressWarning parameter');
}
// </debug>
loadingComponent = Ext.Viewport;
}
var alreadyMasked = loadingComponent.getMasked();
var lastMaskedContainer = this.lastMaskedContainer;
if (!alreadyMasked && !suppressWarning) {
// <debug>
if (lastMaskedContainer != container) {
console.warn('Found Start/Stop Loading inconsistency. Please revise code'
+ (container ? '. Container: ' + container.getId() : 'Ext.Viewport')
+ (lastMaskedContainer ? ', last masked container: ' + lastMaskedContainer.getId() : '')
);
}
// </debug>
loadingComponent = Ext.Viewport;
}
loadingComponent.setMasked(false);
}
比在水龙头处理程序中:
onDealDetailsTap: function(ct) {
console.log('onDealDetailsTap', ct);
var form = ct.getReferenceForm(),
navigatorContainer = this.getNavigatorContainer(form),
model = form.getRecord();
UiHelper.startLoading(navigatorContainer);
Ext.Viewport.fireEvent('detailfields', {
title: model.get('title'),
id: model.get('id'),
store: 'DealFields',
navigatorContainer: navigatorContainer
})
},
清理加载掩码:
control : {
activitiesContainer: {
push: 'onPushActivitiesContainer'
},
onPushActivitiesContainer: function(ct) {
//console.log('onPushActivitiesContainer', ct);
UiHelper.stopLoading(ct);
},
特别是等待长时间的ajax请求很酷......
干杯,奥列格
只需在点击按钮时暂停按钮上的事件,并在按下视图时恢复它们
button.suspendEvents();
...
button.resumeEvents();
我不认为有其他方法。作为开发人员或用户,当您点击一个按钮两次时,您希望事件处理程序被调用两次。
希望这可以帮助
只需遮盖整个容器,然后将其取消遮盖;为控制器中存在按钮的容器或面板创建一个引用,并在点击集上:
ref.setMasked(true)
推送新视图后,只需取消屏蔽
ref.setMasked(false)
另一种方法是在列表项被点击一次后翻转参数,如下所示:
{
onListItemTap: function () {
if (!this.tapped) {
this.tapped = true;
...
}
}
}
当然,这只有在用户一进入另一个屏幕就破坏列表视图时才有效。
我创建了一种检查方法:
ENSURE_NO_DOUBLE_TAP : function(classNameToPush) {
if (Ext.getClassName(Ext.getCmp('MyViewport').getActiveItem()) == classNameToPush) {
return false;
}
return true;
}
然后从您的应用程序中处理任何可能被双击的内容:
if (!ENSURE_NO_DOUBLE_TAP('MyApp.view.View')) {
return;
}
如果您正在使用侦听器收听按钮的点击事件,那么这是我的解决方案:
listeners : {
release : function(){
if(this.getDisabled())return false;
this.setDisabled(true);
this.fireEvent('tap');
},
tap : function() {
//do what you want
}
}
扩展 jayteejee 和 Merott 的答案,我添加了一些代码来拦截多个快速推送,不仅可以防止重复,还可以防止在页面转换完成之前推送不同的视图。想象一个用户点击不同的列表项。
还要注意view.destroy();
else 块中的方法,以防止视图实例在内存中堆积。
Ext.define('Overrides.navigation.View', {
extend: 'Ext.navigation.View',
xtype: 'ovrnavigationview',
interceptPush: false,
push: function (view) {
var activeItem = this.getActiveItem();
// Prevent multiple pushes & duplicates
if (!this.interceptPush && activeItem.xtype !== view.xtype) {
// Set interceptPush
this.interceptPush = true;
// Reset interceptPush after 500 ms
Ext.defer(function() {
this.interceptPush = false;
}, 500, this);
// Handle push
this.callParent(arguments);
} else {
// Warn developer
console.warn("Prevented pushing view of xtype: " + view.xtype);
// Destroy view
view.destroy();
return false;
}
}
});
您可以只使用“itemsingletap”事件。
如果您也想支持双击,请为“itemdoubletap”创建第二个侦听器并调用相同的函数,两个侦听器一起工作得很好。