使代理使用扩展Ext.data.Operation

Aci*_*ier 5 proxy extjs datastore extjs4 extjs-mvc

我已经扩展Ext.data.Operation到实现自定义commitRecords方法.

Ext.data.Operation类用于商店和其代理之间的所有通信.

commitRecords方法具体用于根据从代理写入器返回的数据更新数据存储中的数据.

我似乎无法掌握如何设置代理以使用我的扩展版本Ext.data.Operation.

我一直在搜索Ext.data.*包,但似乎无法找到Ext.data.Operation创建的位置,所以我将知道要使用Ext.data.Operation自定义commitRecords方法使用这个新的扩展类的类.

有没有其他人延长过这个,可以给我一些指示?

Aci*_*ier 4

我发现它的batch方法Ext.data.Proxy是创建一个Ext.data.Operation对象发送到服务器。

Ext.data.proxy.Ajax用一种新batch方法进行了扩展,我只是将 切换new Ext.data.Operation为我自己的操作类。

编辑

只是因为你问了 DmitryB。关于为什么我必须实现自己的 commitRecords 方法的简短故事是,我需要我的数据模型“internalId”字段来匹配实际的数据库记录 ID 字段。我不会详细解释为什么,这对我来说太复杂了,无法表达,但这就是我所做的:

我的理解是,该commitRecords方法作为最后一个操作之一被触发,当调用它时,store.sync()只要您编写服务器端控制器以返回新的服务器记录,它就会自动用新的服务器端记录替换客户端上的脏记录。 Ajax 响应,只要同步请求执行插入或更新,它就会执行此操作。

官方实现commitRecords尝试使用数据模型的“internalId”字段将返回的服务器记录与脏客户端记录进行匹配。

显然,我不知道新记录的下一个增量数据库 ID 是什么,所以我无法在客户端将其分配为记录与数据库同步之前的 ID,因此服务器记录将永远无法匹配当调用 commitRecords 时,与脏客户端记录的内部 ID 进行匹配,即客户端记录将无法获得我需要的正确数据库 ID。

因此,因为该应用程序的所有可写数据模型都有一个“create_time”字段,所以我决定使用“create_time”字段而不是“internalId”使 commitRecords 方法将服务器记录与客户端记录进行匹配。

这是扩展的 Ext.data.Operation 类,我在其中执行了此操作:

Ext.define('MyApp.ux.QueryOperation', {
    extend: 'Ext.data.Operation',

    /** 
     * Use the date_created timestamp if we cant match to an ID.
     * This allows client records that did not previously exist on the server
     * to be updated with the correct server ID and data
     * NB: All implementing data models require a "date_created" field.
     */
    commitRecords: function (serverRecords) {
        var me = this,
            mc, index, clientRecords, serverRec, clientRec;
        if (!me.actionSkipSyncRe.test(me.action)) {
            clientRecords = me.records;
            if (clientRecords && clientRecords.length) {
                if (clientRecords.length > 1) {
                    mc = new Ext.util.MixedCollection();
                    mc.addAll(serverRecords);
                    Ext.each(clientRecords, function(clientRec) {
                        serverRec = mc.findBy(function(record) {
                            var clientId = clientRec.getId(),
                                clientTime = clientRec.get('date_created').getTime(),
                                serverTime = record.get('date_created').getTime();
                                if(clientId && record.getId() === clientId) {
                                    return true;
                                }
                                // timestamp can be within 2ms of record
                                // (it seems to change slightly in serialization)
                                return (clientTime > serverTime - 2 && clientTime < serverTime + 2);
                        });
                        me.updateClientRecord(clientRec, serverRec);
                    });
                } else {
                    clientRec = clientRecords[0];
                    serverRec = serverRecords[0];
                    me.updateClientRecord(clientRec, serverRec);
                }
                if (me.actionCommitRecordsRe.test(me.action)) {
                    for (index = clientRecords.length; index--; ) {
                        clientRecords[index].commit();
                    }
                }
            }
        }
    },

});
Run Code Online (Sandbox Code Playgroud)

正如我在答案中提到的,我发现我必须扩展代理才能使用我的新操作类。我唯一扩展的是batch方法,只替换了方法中的两行,即new Ext.data.Operation现在所说的new MyApp.ux.QueryOperation(上面我的新操作类)。当服务器返回响应时,这会调用我自己的 commitRecords 方法。我还为扩展代理提供了一个别名“proxy.query”,以便我可以告诉我的商店像这样使用它:

Ext.define('MyApp.store.MyStore', {
    extend: 'Ext.data.Store',
    requires: [
        'ST.ux.QueryProxy',
    ],
    title: 'Student',
    model: 'MyApp.model.MyModel',
    proxy: {
        type: 'query',
        // ... ^^^^^ uses my QueryProxy now
        // other configs...
    }
});
Run Code Online (Sandbox Code Playgroud)

(如果我似乎采取了错误的方式或错过了文档中的某些内容,请告诉我。我会更高兴使用实现此功能的内置方法。)