现代工具包中的 Extjs 选项卡面板 tabchange 事件

Extjs Tab Panel tabchange event in modern toolkit

我正在使用 ExtJS 7.5 现代工具包。我最初在经典工具包中开发了一个带有路由器的应用程序,该应用程序基于下面显示的示例,使用路由器并监听选项卡面板上的 tabchange 事件。我们决定为应用程序更改为现代工具包,但我似乎无法弄清楚如何复制 tabchange 行为,因为现代工具包中似乎不存在 tabchange 事件。

我能找到的最接近的事情是 activeitemchange 事件,但在使用路线时这会成为一个问题,因为在处理路线时我需要更新触发该事件的活动选项卡,随后导致另一个重定向到另一条路线。 tabchange 事件不受设置活动项目的影响,似乎只受到实际单击/触摸另一个选项卡的影响。

经典工具包中的示例:

Ext.define('Router.controller.Navigation', {
    extend: 'Ext.app.Controller',

    config: {
        control: {
            '#main-tabs': {
                tabchange: 'onTabChange'
            },
            '#tab6': {
                tabchange: 'onChildTabChange'
            }
        },
        refs: {
            tabPanel: '#main-tabs'
        },
        routes: {
            'main-tabs:id:subid': {
                action: 'showTab',
                before: 'beforeShowTab',
                conditions: {
                    // take control of the :id & :subid parameters, make them optional but delimited by colon
                    ':id': '(?:(?::){1}([%a-zA-Z0-9\-\_\s,]+))?',
                    ':subid': '(?:(?::){1}([%a-zA-Z0-9\-\_\s,]+))?'
                }
            }
        }
    },

    onTabChange: function(tabPanel, newItem) {
        var id = newItem.getId(),
            child = newItem.child('tabpanel'),
            subid = '',
            hash = 'main-tabs:' + id;

        if (child) {
            newItem = child.getActiveTab();
            subid = ':' + newItem.getId();

            hash += subid;
        }

        this.redirectTo(hash);
    },

    onChildTabChange: function(tabPanel, newItem) {
        var parentTab = tabPanel.up(),
            parentId = parentTab.getId(),
            hash = 'main-tabs:' + parentId + ':' + newItem.getId();

        this.redirectTo(hash);
    },

    beforeShowTab: function(id, subid, action) {
        var tabPanel = this.getTabPanel(),
            child;

        if (!id) {
            // no id was specified, use 0 index to resolve child
            id = 0;
        }

        child = tabPanel.getComponent(id);

        if (child) {
            // tab found, resume the action
            action.resume();
        }
        else {
            Ext.Msg.alert('Tab Not Found', 'Tab with id or index "<b>' + id + '</b>" was not found!');

            // child not found, stop action
            action.stop();
        }
    },

    showTab: function(id, subid) {
        var tabPanel = this.getTabPanel(),
            child, childTabPanel;

        if (!id) {
            // no id was specified, use 0 index to resolve child
            id = 0;
        }

        child = tabPanel.getComponent(id);

        childTabPanel = child.child('tabpanel');

        tabPanel.setActiveTab(child);

        if (childTabPanel) {
            if (!subid) {
                subid = 0;
            }

            childTabPanel.setActiveTab(subid);
        }
    }
});

Ext.application({
    name: 'Router',

    requires: [
        'Ext.tab.Panel',
        'Ext.window.MessageBox'
    ],

    controllers: [
        'Navigation'
    ],

    defaultToken: 'main-tabs',

    launch: function() {

        Ext.create('Ext.tab.Panel', {
            renderTo: Ext.getBody(),
            id: 'main-tabs',
            height: 300,
            width: 600,
            activeTab: 0,
            defaults: {
                padding: 10
            },
            items: [
                {
                    title: 'Tab 1',
                    id: 'tab1',
                    layout: 'fit',
                    items: [
                        {
                            xtype: 'tabpanel',
                            id: 'tab6',
                            items: [
                                {
                                    title: 'Sub-tab 1',
                                    id: 'subtab1'
                                },
                                {
                                    title: 'Sub-tab 2',
                                    id: 'subtab2'
                                },
                                {
                                    title: 'Sub-tab 3',
                                    id: 'subtab3'
                                }
                            ]
                        }
                    ]
                },
                {
                    title: 'Tab 2',
                    id: 'tab2',
                    html: 'Tab 2 content'
                },
                {
                    title: 'Tab 3',
                    id: 'tab3',
                    html: 'Tab 3 content'
                },
                {
                    title: 'Tab 4',
                    id: 'tab4',
                    html: 'Tab 4 content'
                },
                {
                    title: 'Tab 5',
                    id: 'tab5',
                    html: 'Tab 5 content'
                }
            ]
        });

    }
});

现代的正确事件是activeitemchange

            xtype: 'tabpanel',
            ...
            listeners: {
                activeitemchange: function(tabpanel, newTab) {
                    console.log(newTab.getId());
                    
                }
            }

监听 activeitemchange 事件时,我在使用后退/前进浏览器按钮、处理路由和使用 tabpanel.setActiveItem() 时会遇到问题。这将触发 activeitemchange 事件,导致另一个(不必要的重定向)。

我改为使用 beforeactiveitemchange 事件,它允许我在设置活动项目时暂停处理程序中的事件,因此不再发生重定向并且活动项目更改仍按预期运行。

    control: {
        '#main-tabs': {
            beforeactiveitemchange: 'onMainTabChange'
        },
    }

    //Within the handler func that handles the route
    tabPanel.suspendEvent('beforeactiveitemchange');
    tabPanel.setActiveItem(tab);
    tabPanel.resumeEvent('beforeactiveitemchange');