Ext.bind在ExtJS中看不到功能 [英] Ext.bind does not see function in ExtJS

查看:91
本文介绍了Ext.bind在ExtJS中看不到功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to mod the Portlet example and port it into our program. The code looks like this:

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函数,浏览器给了我一个

The problem is that Ext.bind cannot read the onPortletClose function and the browser gives me a:

Uncaught TypeError: Cannot read property 'apply' of undefined错误.我检查了堆栈,实际上在Ext.bind(fn,scope)中,fn是未定义的,因此它无法读取处理程序函数.我的应用程序和该示例之间的区别是,我将其直接添加到JSP的Ext.onReady()中,而在示例中,所有这些都是通过Ext.apply(this, {...})添加的.我真的很困惑我尝试了各种头来将范围强制施加在视口上,但Ext.bind()内部的任何东西似乎都失去了与外部或其他物体的接触.我以前使用过Ext.bind(),尽管它在initComponent配置中,但运行良好.这是强制性的吗?如果没有,那是什么问题?

Uncaught TypeError: Cannot read property 'apply' of undefined error. I checked the stack and essentially in the Ext.bind(fn,scope) the fn is undefined and thus it cannot read the handler function. The difference between my application and in the example is that I add this directly into a JSP's Ext.onReady() whereas in the example all of this is added through a Ext.apply(this, {...}). I'm really confused. I tried all kinds of gimmicks to force the scope on the viewport but it seems that whatever is inside Ext.bind() loses contact with outside or something. I've used Ext.bind() before and it went fine although it was inside an initComponent configuration. Is that mandatory? If no then what is the problem?

推荐答案

在这里(或通常在使用JavaScript或ExtJS时)理解this的含义很重要.

It is important to understand the meaning of this here (or in general when working with JavaScript or ExtJS).

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

In a global context, this refers to the global object, also known as the global window variable. This is the case inside your Ext.onReady function:

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

在对象上下文中,默认情况下 this引用该函数的所有者对象(存在多种方法,而实际上这正是您想要使用Ext.bind实现的):

In an object context, by default this refers to the owner object of the function (there are ways around it and actually this is exactly want you want do achieve using Ext.bind):

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

现在,这正是使您的案例与示例中的案例有所不同的原因.

Now, this is exactly what makes the difference between your case and the one from the examples.

将方法与Ext.onReadythis一起使用时-如上文所指出-将引用全局对象,该对象当然不具有函数onPortletClose.

When using the approach with Ext.onReady this - as pointed out above - will refer to the global object, which of course does not have a function onPortletClose.

使用示例中的方法时,this是从initComponent内部访问的,该内部函数是派生的视口类的成员函数,因此this引用组件实例(=拥有的对象) ,这使您可以访问功能.

When using the approach from the examples, this is accessed from inside of initComponent, which is a member function of your derived viewport class, and therefore this refers to the component instance (= the owning object), which allows you to access your function.

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

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

Side notes

Ext.apply

Ext.apply really just copies all properties from one object to another, so in this case it is just a convenient way of applying all attributes of that object to this with one function call. You could as well just use:

this.items = [...];

改变听众的范围

向组件添加侦听器时,无需使用Ext.bind,只需在listeners对象中提供scope配置:

Changing the scope of your listeners

You do not need to use Ext.bind when adding listeners to a component, you can simply provide a scope configuration in your listeners object:

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

外部来源

如果您想更深入地学习(我建议这样做),您可能想在 查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆