为控制器中的商店事件设置监听器

Posted

技术标签:

【中文标题】为控制器中的商店事件设置监听器【英文标题】:Set listener for store events in a controller 【发布时间】:2011-11-03 20:05:07 【问题描述】:

我有一个带有商店、模型和一些视图的控制器。

我需要在控制器中监听store的beforesyncwrite事件,但是不知道如何在控制器control-function中设置这些监听器。

我的店铺是这样的:

Ext.define('DT.store.UsersStore', 
    extend : 'Ext.data.Store',
    model : 'DT.model.User',
    id : 'myStore'
    autoSync : true,
    proxy : 
        type : 'ajax',
        api : 
            read : '/load_entries',
            update : '/update_entry'
        ,
        reader : 
            type : 'json',
            root : 'user',
            successProperty : 'success'
        
    
);

现在我尝试监听控制器中的事件:

...
init : function () 
    this.control(
        'myStore' : 
            beforesync : this.doSomething,
            write : this.doSomethingElse
        
    );
,
...

我的预期结果是,当事件被触发时,函数将被执行。 但是此时他们被解雇时什么都没有发生。

我怎样才能让它工作?

【问题讨论】:

【参考方案1】:

Your way 是可能的,但它并不理想,IMO。更好的方法是使用控制器的 store getter。在您的情况下,代码将是这样的:

init : function () 
    // every controller has getters for its stores.
    // For store UsersStore getter would be getUsersStoreStore()
    this.getUsersStoreStore().addListener('write',this.finishedLoading, this);
    this.control(
        // widgets event handlers
    );
,

【讨论】:

比我的解决方案还要好。谢啦。这个社区很棒。 仅在应用程序的一部分使用您定义的控制器时执行代码,此解决方案是否可以正常工作?或者从现在开始,事件是否会影响到这个新的监听器? 我认为它只能在这个控制器内部工作,但我不知道具体,因为我从来没有在一个应用程序中使用过多个控制器。 ST2.1 beta 中似乎没有商店的getter【参考方案2】:

这是Molecular Man's answer 的替代语法。

而不是写作,

init : function () 
    this.getUsersStoreStore().addListener('write',this.finishedLoading, this);
    this.control(
        // widgets event handlers
    );
,

你可以写

init : function () 
    this.getUsersStoreStore().on(
        write: this.finishedLoading,
        scope: this
    );
    this.control(
        // widgets event handlers
    );
,

我认为这个替代定义读起来更好一些。

这是我从answer Izhaki 给我的。

【讨论】:

我们可以使用 on() 添加超过 1 个监听器吗? 在此页面上的所有解决方案中,只有 this.getUsersStoreStore().on(.. 对我有用。 (使用 4.2.1)【参考方案3】:

对于 Extjs 4.2.1,如果您使用 'storeId' 而不是 id 和 'listen' 函数而不是 'control',那么您访问商店侦听器的初始方式实际上会起作用:

Ext.define('DT.store.UsersStore', 
    extend : 'Ext.data.Store',
    model : 'DT.model.User',
    storeId : 'myStore'
    ....

init : function () 
    this.listen(
        store: 
           '#myStore' : 
               beforesync : this.doSomething,
               ...

【讨论】:

【参考方案4】:
Ext.define('Store', 
    model: 'Model',
    extend: 'Ext.data.Store',
    listeners: 
        'beforesync': function()
            App.getController('somecontroller').onBeforeSync();
        
    
);

App - 你的应用程序对象 您可以在控制器中实现 onBeforeSync 功能......这是我可以将事件分配给商店并仍然在控制器中实现逻辑的唯一方法。希望对你有帮助

【讨论】:

不,这不起作用。 this.doSomething 应该执行一个 console.log('BeforeSync');但仍然没有任何反应 好吧,问题显然是监听器没有分配给组件。您应该阅读 extjs 中的查询文档,该文档用于确定为哪个组件分配事件。尝试类似'widgetname gridPanel #store'(其中widgetname 是分配给控制器的视图)。我目前没有要测试的东西,但是您应该逐步进行,首先在包含该商店的组件上添加一个事件,然后尝试在商店上设置事件。 D'oh... 我发现 store 类既没有 id 也没有别名配置。我的配置将被忽略,并且该项目不会在控制器中分配。还有其他方法吗? 我搜索了替代品,但找不到任何替代品。控制功能使用组件查询来获取组件,并且存储它不是 ext 组件,它扩展了 ext.base,因此我相信使用组件查询获取商店是不可能的。我找到了一个替代方案,我会用我找到的解决方案修改上面的答案 请不要将你的 store 耦合到控制器,这是一个非常糟糕的主意,你不能在应用程序的其他部分重用这个 store。【参考方案5】:

我自己解决了。

我在面板的render-event 中手动添加了监听器

Ext.getCmp('userPanel').down('gridpanel').getStore().addListener('write',this.finishedLoading, this);

感谢@nscrob 的帮助。

【讨论】:

【参考方案6】:

希望这个添加可以帮助人们避免花费一些时间来调试库核心:

与使用控制器的 getter 方法访问控制器内部的 Ext.data.Store 实例的这种做法有关:例如对于上面的“DT.store.UsersStore”,使用 this.getUsersStoreStore():

注意,如果商店已经在视图中关联(例如,被声明为“UsersGrid”Grid.panel.Panel 小部件定义的商店属性),那么这个 getter 方法实际上将检索另一个实例相同的 Store 类,而不是小部件使用的实例! 原因是在构造函数配置对象中添加存储是这样的:

stores: ['UsersStore']

实际上将在 Ext.data.StoreManager.map 哈希中添加一个新的商店实例 - 假设 'UsersStore' 是迄今为止唯一实例化的商店对象 - 地图键现在看起来像:

0: "ext-empty-store"
1: "UsersStore"
2: "myStore"

现在假设您想使用您的 store'proxy 读取一些新数据并在“UsersGrid”中显示这些新数据,并且您希望在用户单击某物时执行所有这些操作,因此在控制器内部您将有一个处理程序方法带有代码的用户事件:

'user-selector' : 
    click: function()
                     var oStoreReference = this.getUsersStoreStore();
                         oStoreReference.load( params: );
            
    

获取引用的调用将在 this.getStore('UsersStore') 内部翻译,并将返回对生成的控制器的引用 - 1:“UsersStore” - 而不是 - 2:“myStore” - 可能预期的。此外,load() 调用将使用新模型加载 UsersStore 实例,这不会反映在您的网格视图中(因为网格已绑定并监听“myStore”存储实例生成的事件)。

所以最好使用通用 getStore 方法通过 itemId 访问商店:this.getStore('storeItemId')

【讨论】:

【参考方案7】:

为什么不直接转播商店的活动?例如:

this.getUsersGrid().relayEvents(this.getUsersStoreStore(), ['write'], 'store')

然后就可以了

this.control('somegrid-selector': storeWrite: function()...)

【讨论】:

【参考方案8】:

以防万一有人为此绊倒。

ExtJS 7.3

Ext.define('DT.controller.UsersStore', 
    extend: 'Ext.app.Controller',

    listen: 
        store: 
            UsersStore: 
                beforesync : 'doSomething',
                write : 'doSomethingElse'
            
        
    ,

    doSomething() 
        console.log(arguments)
    ,

    doSomethingElse() 
        console.log(arguments)
    
);

【讨论】:

以上是关于为控制器中的商店事件设置监听器的主要内容,如果未能解决你的问题,请参考以下文章

通量控制器视图未订阅商店中的事件更改

视图应该直接打电话给商店吗?

iOS:什么是Objective-C中的事件监听器?

如何为控制台命令创建监听器

在商店中触发操作是不好的做法吗?

在 initComponent 中声明时,事件侦听器未调用控制器方法