Sencha Touch:快速单击按钮将推动视图两次

时间:2012-07-17 12:45:14

标签: extjs sencha-touch sencha-touch-2

假设我有一个触发推送新视图的按钮。 我注意到,如果我多次点击它,速度足够快,它会将同一个视图推两次。

您可以使用此页面上的官方文档来模仿此行为,其中包含实时示例: http://docs.sencha.com/touch/2-0/#!/guide/navigation_view

明确的问题是,如何预防?

10 个答案:

答案 0 :(得分:8)

另一种方法是检查活动视图是什么,只有当它与您要推送的视图不同时才推送。我已经测试了这个并且它可以工作。

E.g。

if (this.getNavigationView().getActiveItem().xtype != "someView") {
    this.getNavigationView().push({ xtype: "someView" });
}

答案 1 :(得分:6)

扩展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不起作用!

答案 2 :(得分:4)

遮蔽成功防止了双击问题。

在我的代码中,我使用两个函数作为mask / unmask导航容器:

/**
 * 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请求很酷....

干杯,奥列格

答案 3 :(得分:2)

点击按钮时暂停按钮,并在按下视图时恢复它们

button.suspendEvents();
...
button.resumeEvents();

我认为还有另一种方式。作为开发人员或用户,当您点击两次按钮时,您希望调用事件处理程序两次。

希望这有帮助

答案 4 :(得分:2)

简单地掩盖整个容器,然后取消屏蔽它;为控制器中存在按钮的容器或面板创建一个ref,并点击设置:

ref.setMasked(true)

按下新视图后,只需通过

取消屏蔽
ref.setMasked(false)

答案 5 :(得分:0)

另一种方法是在列表项被轻敲一次后翻转参数,如下所示:

{
   onListItemTap: function () {
      if (!this.tapped) {
         this.tapped = true;
         ...
      }
   }
}

当然,只有在用户转到不同的屏幕时才会销毁列表视图,这才有效。

答案 6 :(得分:0)

我创建了一个检查它的方法:

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

答案 7 :(得分:0)

如果您正在使用听众收听按钮的点击事件,那么这里是 我的解决方案:

listeners : {   
     release : function(){                                  
          if(this.getDisabled())return false;
          this.setDisabled(true);
          this.fireEvent('tap');
     },
     tap : function() {
         //do what you want
     }
 }

答案 8 :(得分:0)

扩展jayteejee和Merott的答案,我添加了一些代码来拦截多次快速推送,不仅可以防止重复,还可以防止在页面转换完成之前推送不同的视图。想想用户点击不同的列表项。

另请注意else块中的view.destroy();方法,以防止视图实例堆积在内存中。

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

答案 9 :(得分:0)

您可以使用“itemsingletap”事件。

如果你想支持双击,为“itemdoubletap”做一个第二个监听器并调用相同的函数,两个监听器都可以很好地协同工作。