gpt4 book ai didi

extjs - 如何正确地从另一个 Controller 或闭包调用 Controller 方法

转载 作者:行者123 更新时间:2023-12-03 15:16:52 27 4
gpt4 key购买 nike

我是 extjs 的新手,我正在使用 MVC 架构。
当我的应用程序引用 Controller 的方法时,我会这样做(在 MyApp.Application 中):

Mb.app.getController('Main').myMethod();
它已经很长了,但我认为这是这样做的方法。
当 Controller 在闭包中调用它自己的方法时,我被引导使用此代码(在 MyApp.controller.Main 中:
controllerMethodOne: function(){
Ext.Ajax.request({
url: ...,
params: ...,
success: (function(response){
list = Ext.JSON.decode(response.responseText);
list.forEach(function(item){
storeMenu.add(
Ext.create('Ext.menu.Item', {
text: item.text,
handler: function(el){MyApp.app.getController('Main').controllerMethodTwo()}
})
)
})
})
})
},
我用 MyApp.app.getController('Main').controllerMethodTwo() 引用了该方法因为 this没有引用闭包中的 Controller 对象,因此 this..controllerMethodTwo()不工作。
我觉得这完全令人费解,我希望有人有一个想法来解决这个问题 MyApp.app.getController - 解决方法。
更新
感谢所有建议,我可以优化我的代码并提出:
// in my controller
mixins: ['Mb.controller.mixin.StoreMenu'],
// I use that style of menus in two controllers thats why I use a mixin
init: function() {
this.control({
'#vg_storeMenu menuitem': {
click: this.onStoreMenuClicked
}
})
},

// the controller mixin
Ext.define('Mb.controller.mixin.StoreMenu', {
extend: 'Ext.app.Controller',
buildStoreMenu: function(store_name){
var storeMenu = Ext.ComponentQuery.query('#' + store_name + 'Menu')[0];
Ext.Ajax.request({
url: Paths.ajax + 'json.php',
params: {list: store_name + 's'},
success: (function(response){
list = Ext.JSON.decode(response.responseText);
items = Ext.Array.map(list, function(item) {
return {
xtype: 'menuitem',
text: item.text
}
});
storeMenu.add(items);
})
})
},
onStoreMenuClicked: function(el){
...
}
});

最佳答案

实际上,您的代码中至少存在四个明显不同的问题:

  • 类内方法调用的范围处理
  • 组件创建效率低下
  • Controller 中的组件事件处理
  • Controller 间通讯

  • 范围处理

    第一个问题可以通过使用闭包或将范围参数传递给 Ajax 请求来解决,如上文所述的@kevhender。鉴于此,我主张编写更清晰的代码:
    controllerMethodOne: function() {
    Ext.Ajax.request({
    url: ...,
    params: ...,
    scope: this,
    success: this.onMethodOneSuccess,
    failure: this.onMethodOneFailure
    });
    },

    // `this` scope is the controller here
    onMethodOneSuccess: function(response) {
    ...
    },

    // Same scope here, the controller itself
    onMethodOneFailure: function(response) {
    ...
    }

    组件创建

    创建菜单项的方式效率不高,因为每个菜单项都将被创建并一一呈现给 DOM。这也几乎没有必要:您预先拥有项目列表并且您可以控制,所以让我们保持代码的美观和声明性,并一次性创建所有菜单项:
    // I'd advocate being a bit defensive here and not trust the input
    // Also, I don't see the `list` var declaration in your code,
    // do you really want to make it a global?
    var list, items;

    list = Ext.JSON.decode(response.responseText);
    items = Ext.Array.map(list, function(item) {
    return {
    xtype: 'menuitem',
    text: item.text
    }
    });

    // Another global? Take a look at the refs section in Controllers doc
    storeMenu.add(items);

    这里的变化是我们正在迭代 list并创建一个新的即将成为菜单项声明的数组。然后我们一次性将它们全部添加,在重新渲染和重新布局您的 storeMenu 时节省大量资源.

    组件偶数处理

    在每个菜单项上设置一个处理函数是完全没有必要的,而且效率很低,因为这个函数所做的只是调用 Controller 。当一个菜单项被点击时,它会触发 click事件 - 你需要做的就是连接你的 Controller 来监听这些事件:
    // Suppose that your storeMenu was created like this
    storeMenu = new Ext.menu.Menu({
    itemId: 'storeMenu',
    ...
    });

    // Controller's init() method will provide the wiring
    Ext.define('MyController', {
    extend: 'Ext.app.Controller',

    init: function() {
    this.control({
    // This ComponentQuery selector will match menu items
    // that descend (belong) to a component with itemId 'storeMenu'
    '#storeMenu menuitem': {
    click: this.controllerMethodTwo
    }
    });
    },

    // The scope is automatically set to the controller itself
    controllerMethodTwo: function(item) {
    ...
    }
    });

    一种最佳实践是尽可能细粒度地编写 ComponentQuery 选择器,因为它们是全局的,如果您不够精确,您的 Controller 方法可能会捕获来自不需要的组件的事件。

    Controller 间通信

    目前这可能有点牵强,但由于您使用的是 Ext JS 4.2,您不妨利用我们在这方面添加的改进。在 4.2 之前,有一种首选的(也是唯一的)方法可以从另一个 Controller 调用一个 Controller 的方法:
    Ext.define('My.controller.Foo', {
    extend: 'Ext.app.Controller',

    methodFoo: function() {
    // Need to call controller Bar here, what do we do?
    this.getController('Bar').methodBar();
    }
    });

    Ext.define('My.controller.Bar', {
    extend: 'Ext.app.Controller',

    methodBar: function() {
    // This method is called directly by Foo
    }
    });

    在 Ext JS 4.2 中,我们添加了事件域的概念。这意味着现在 Controller 不仅可以监听组件的事件,还可以监听其他实体事件。包括他们自己的 Controller 域:
    Ext.define('My.controller.Foo', {
    extend: 'Ext.app.Controller',

    methodFoo: function() {
    // Effectively the same thing as above,
    // but no direct method calling now
    this.fireEvent('controllerBarMethodBar');
    }
    });

    Ext.define('My.controller.Bar', {
    extend: 'Ext.app.Controller',

    // Need some wiring
    init: function() {
    this.listen({
    controller: {
    '*': {
    controllerBarMethodBar: this.methodBar
    }
    }
    });
    },

    methodBar: function() {
    // This method is called *indirectly*
    }
    });

    这可能看起来像是一种更复杂的做事方式,但实际上它在大型(ish)应用程序中使用起来要简单得多,并且它解决了我们遇到的主要问题:不再需要 Controller 之间的硬绑定(bind),您可以独立于其他 Controller 测试每个 Controller 。

    在我的博文中查看更多信息: Controller events in Ext JS 4.2

    关于extjs - 如何正确地从另一个 Controller 或闭包调用 Controller 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19253885/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com