1

来自 C++ 背景,我对 Javascript/ExtJS 函数作用域有点迷失 - 特别是在处理事件时。

假设我有一个控制器可以监听许多不同的事件。这些事件可能来自托管视图、商店、应用程序级别等。目前,我正在做这样的事情来确保正确的范围界定:

init: function() {
    me.control({
        'someSelector': {
            someEvent: me.onSomeEvent.bind(me)
        },
        ...
    });
    me.application.on({
        applicationEvent: me.onApplicationEvent.bind(me)
    });
},
onSomeEvent: function() {...},
onApplicationEvent: function() {...},

这是做事的正确方式吗?我害怕在this里面使用onSomeEvent()onApplicationEvent除非我知道具体this指向什么。想法?

编辑:这里有一些示例代码来显示this可能会产生误导的地方。

init: function() {
    this.control({
        'uploadform *': {
            formUpload: this.onFormUpload
        }
    });
},

onFormUpload: function(form) {
    if(form.isValid()) {
        var formData = form.getValues();
        Ext.Ajax.request({
            url: 'upload',
            method: 'POST',
            jsonData: {
                form: formData
            },
            success: this.onFormUploadSuccess // here, this is the controller
        });
    }
},

onFormUploadSuccess: function() {
    ...                                       // here, this isn't the controller
    this.application.fireEvent('dealAdded');  // this.application === undefined!!
}
4

1 回答 1

3

尽管 JS 中的作用域可能会令人困惑,但不要害怕它。您的控制器维护范围,因此您不需要丑化您的代码。它应该如下所示:

Ext.define('Pandora.controller.Station', {
    extend: 'Ext.app.Controller',
    ...    
    init: function() {
        this.control({
            'stationslist': {
                selectionchange: this.onStationSelect
            },
            ...
        });
    },    
    ...    
    onStationSelect: function(selModel, selection) {
        this.application.fireEvent('stationstart', selection[0]);
    },    
   ...
});

这里有一篇出色的事件处理帖子:Explain ExtJS 4 event handling。此外,当某些事情看起来不正确时,我会求助于console.log(this)确保我正在查看正确的范围。

编辑 在看到您提供的示例后,问题不在控制器本身,而是在 Ajax 请求是异步的并且默认在 Window 范围内执行。ExtJS 允许您scope:this在请求中使用 config 设置范围,这会将控制器设置为成功回调的范围。

Ext.Ajax.request({
            url: 'upload',
            method: 'POST',
            jsonData: {
                form: formData
            },
            success: this.onFormUploadSuccess // here, this is the controller
     ,scope:this
        });
于 2013-09-13T21:03:55.823 回答