为控制器中的存储事件设置侦听器

Set listener for store events in a controller

本文关键字:事件 设置 侦听器 存储 控制器      更新时间:2023-09-26

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

我需要在控制器中侦听存储的beforesyncwrite事件,但我不知道如何在控制器control-函数中设置这些侦听器。

我的商店看起来是这样的:

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
        }
    });
},
...

我的预期结果是,当事件被激发时,函数将被执行。但在这个时候,当他们被解雇时,什么也没发生。

我怎样才能让它发挥作用?

IMO,您的方法是可行的,但并不理想。更好的方法是使用控制器的存储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
    });
},

这是Molecular Man答案的另一种语法。

不是写

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
    });
},

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

我从Izhaki给我的答案中得到了这个。

对于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,
               ...
Ext.define('Store', {
    model: 'Model',
    extend: 'Ext.data.Store',
    listeners: {
        'beforesync': function(){
            App.getController('somecontroller').onBeforeSync();
        }
    }
});

应用程序-您的应用程序对象BeforeSync上的功能可以在控制器中实现。。。这是我将事件分配给存储并在controll中实现逻辑的唯一方法。我希望它能帮助

我自己解决了。

我在面板的render-事件中手动添加了侦听器

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

谢谢你的帮助@nscrob。

希望这个添加能帮助其他人避免花几个小时调试库核心:

与使用控制器的getter方法访问Controller内部的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"

现在想象一下,你想使用商店的代理读取一些新数据,并在"UsersGrid"中显示这些新数据,当用户点击某个东西时,你想完成所有这些操作,所以在控制器内部,你将有一个处理用户事件的方法,代码为:

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

获取引用的调用将在此.getStore('UsersStore'(中进行内部转换,并将返回对控制器生成的引用-1:"UsersStore"-而不是-2:"myStore"-正如人们所期望的那样。此外,load((调用将使用新的Models加载UsersStore实例,这将不会反映在网格视图中(因为网格已绑定并侦听"myStore"存储实例生成的事件(。

因此,最好使用通用的getStore方法通过其itemId访问存储:this.getStore('storeItemId'(

为什么不直接中继商店的事件?例如:

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

然后能够

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

以防万一有人为此埋头苦干。

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)
    }
});