javascript - Ext.bind 在 ExtJS 中看不到函数

标签 javascript extjs extjs4

我正在尝试修改 Portlet 示例并将其移植到我们的程序中。代码如下所示:

Ext.create('Ext.container.Viewport',{
            id: 'app-viewport', //creates viewport
            layout: {
                type: 'border',
                padding: '0 5 5 5' // pad the layout from the window edges
            },

            onPortletClose: function(portlet) {
                this.showMsg('"' + portlet.title + '" was removed');
            },

            showMsg: function(msg) {
                var el = Ext.get('app-msg'),
                    msgId = Ext.id();

                this.msgId = msgId;
                el.update(msg).show();

                Ext.defer(this.clearMsg, 3000, this, [msgId]);
            },

            clearMsg: function(msgId) {
                if (msgId === this.msgId) {
                    Ext.get('app-msg').hide();
                }
            },

            items: [{
                id: 'app-header',
                xtype: 'box',
                region: 'north',
                height: 40,
                html: 'Ext Welcome'
            },{
                xtype: 'container',
                region: 'center',
                layout: 'border',
                items: [{
                    id: 'app-options', //Creates the Options panel on the left
                    title: 'Options',
                    region: 'west',
                    animCollapse: true,
                    width: 200,
                    minWidth: 150,
                    maxWidth: 400,
                    split: true,
                    collapsible: true,
                    layout:{
                        type: 'accordion',
                        animate: true
                    },
                    items: [{
                        html: content,
                        title:'Navigation',
                        autoScroll: true,
                        border: false,
                        iconCls: 'nav'
                    },{
                        title:'Settings',
                        html: content,
                        border: false,
                        autoScroll: true,
                        iconCls: 'settings'
                    }]
                },{
                    id: 'app-portal', //Creates the panel where the portal drop zones are.
                    xtype: 'mainpanel',
                    region: 'center',
                    items: [{
                        id: 'col-1', //Each column represents a drop zone column. If we add more there are more created and width gets adjusted accordingly
                        items: [{
                            id: 'portlet-1',
                            title: 'Portlet 1',
                            html: content,
                            listeners: {
                                'close': Ext.bind(this.onPortletClose, this)
                        },{
                            id: 'portlet-2',
                            title: 'Portlet 2',
                            html: content,
                            listeners: {
                                'close': Ext.bind(this.onPortletClose, this)
                            }
                        }]
                    },{
                        id: 'col-2',
                        items: [{
                            id: 'portlet-3',
                            title: 'Portlet 3',
                            html: content,
                            listeners: {
                                'close': Ext.bind(this.onPortletClose, this)
                            }
                        }]
                    },{
                        id: 'col-3',
                        items: [{
                            id: 'portlet-4',
                            title: 'Portlet 4',
                            html: content,
                            listeners: {
                                'close': Ext.bind(this.onPortletClose, this)
                            }
                        }]
                    }]
                }]
            }]
        });

问题是 Ext.bind 无法读取 onPortletClose 函数,浏览器给我一个:

未捕获类型错误:无法读取未定义的属性“应用” 错误。我检查了堆栈,基本上在 Ext.bind(fn,scope) 中,fn 未定义,因此它无法读取处理程序函数。我的应用程序与示例中的区别在于,我将其直接添加到 JSP 的 Ext.onReady() 中,而在示例中,所有这些都是通过 Ext.apply(this, {...})。我真的很困惑。我尝试了各种花招来强制视口(viewport)上的范围,但似乎 Ext.bind() 内部的任何内容都与外部或其他东西失去了联系。我之前使用过 Ext.bind() ,尽管它位于 initComponent 配置内,但运行良好。这是强制性的吗?如果不是那么问题是什么?

最佳答案

理解这里的 this 的含义(或者一般在使用 JavaScript 或 ExtJS 时)非常重要。

在全局上下文中,this 指的是全局对象,也称为全局window 变量。这是 Ext.onReady 函数内的情况:

Ext.onReady(function() {
    console.log(this === window);
    // -> true
    // because this is the global object
});

在对象上下文中,默认 this 指的是函数的所有者对象(有很多方法可以解决它,实际上这正是您想要使用来实现的) Ext.bind):

var obj = {
   prop: 'My text property',
   fn: function() {
       console.log(this.prop);
       // -> My text property
       // because "this" refers to our object "obj"
   }
};

现在,这正是您的案例与示例中的案例之间的区别。

当使用 Ext.onReady 方法时,this - 如上所述 - 将引用全局对象,该对象当然没有函数 onPortletClose.

使用示例中的方法时,从 initComponent 内部访问 this,它是派生视口(viewport)类的成员函数,因此 this 指的是组件实例(= 所属对象),它允许您访问您的函数。

Ext.define('MyViewport', {
    extend: 'Ext.container.Viewport',

    onPortletClose: function(portlet) {
        this.showMsg('"' + portlet.title + '" was removed');
    },

    initComponent: function() {
        console.log(this);
        // -> the instance of your viewport class

        Ext.apply(this, {
            items:[{
                xtype: 'panel',
                title: 'Portlet 1',
                listeners: {
                    'close': Ext.bind(this.onPortletClose, this)
                }
            }]
        });

        this.callParent();
    }
});

旁注

扩展.应用

Ext.apply实际上只是将所有属性从一个对象复制到另一个对象,因此在本例中,这只是一种通过一次函数调用将该对象的所有属性应用this的便捷方法。您也可以使用:

this.items = [...];

更改监听器的范围

向组件添加监听器时不需要使用 Ext.bind,只需在 监听器 中提供 scope 配置即可对象:

listeners: {
    close: function() {...},
    scope: this
}

外部来源

如果您想更深入地了解(我推荐),您可能需要在 MDN (Mozilla Developer Network) 阅读有关的更多信息。 .

关于javascript - Ext.bind 在 ExtJS 中看不到函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24913743/

相关文章:

javascript - ExtJs 4 - 如何拖放文本(或文本区域)字段的内容?

javascript - 以图案形式 Canvas 随机图像

android - 应用程序构建包后,启动屏幕和启动屏幕之间出现白屏index.html sencha touch

javascript - ExtJS 窗口 setActive() 未按预期工作

javascript - 需要与 EXT JS 工具提示功能相关的帮助

php - 如何使用 extjs url 将 javascript 动态数据发送到 php 变量?

javascript - 如何让 ExtJs RowExpander 仅在某些行上显示图标 ([+])?

javascript - 使用 javascript 从元素中删除类名

javascript - 使用 Canvas 的 id 调整大小?

javascript - 在 ES6 中以正确的方式绑定(bind) "this"