使代理使用扩展的 Ext.data.Operation
Posted
技术标签:
【中文标题】使代理使用扩展的 Ext.data.Operation【英文标题】:Make proxy use extended Ext.data.Operation 【发布时间】:2012-05-17 14:30:10 【问题描述】:我已扩展 Ext.data.Operation
以实现自定义 commitRecords
方法。
Ext.data.Operation
类用于商店与其代理之间的所有通信。
commitRecords
方法专门用于根据代理写入器返回的数据更新数据存储中的数据。
我似乎无法掌握如何设置代理以使用我的扩展版Ext.data.Operation
。
我一直在浏览Ext.data.*
包,但似乎找不到Ext.data.Operation
的创建位置,所以我会知道要告诉哪个类使用这个新的扩展Ext.data.Operation
类和自定义@987654329 @方法。
之前有没有人扩展过这个,能给我一些指点吗?
【问题讨论】:
【参考方案1】:我找到了,Ext.data.Proxy
的batch
方法是创建Ext.data.Operation
对象以发送到服务器的地方。
我使用新的batch
方法扩展了Ext.data.proxy.Ajax
,我只需为我自己的操作类切换new Ext.data.Operation
。
编辑
只是因为你问了 DmitryB。关于我为什么必须实现自己的 commitRecords 方法的简短故事是,我需要我的数据模型“internalId”字段来匹配实际的数据库记录 ID 字段。具体原因我就不说了,太复杂了,我无法表达,但这是我所做的:
我的理解是,commitRecords
方法在调用store.sync()
时作为最后一个操作之一被触发,只要您编写服务器端,它就会自动将客户端的脏记录替换为新的服务器端记录控制器在 Ajax 响应中返回新的服务器记录,它会在同步请求进行插入或更新时执行此操作。
commitRecords
的官方实现尝试通过使用数据模型的“internalId”字段将这条返回的服务器记录与脏客户端记录匹配。
显然,我不知道新记录的下一个增量数据库 ID 将是什么,因此我无法在记录与数据库同步之前在客户端将其分配为 ID,因此服务器记录永远不会匹配能够在调用 commitRecords 时匹配脏客户端记录的 internalId,即客户端记录不会获得我需要的正确数据库 ID。
所以,因为我的所有可写数据模型都有一个“create_time”字段,所以我决定让 commitRecords 方法使用“create_time”字段匹配服务器记录和客户端记录“internalId”。
这是扩展的 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();
,
);
正如我在答案中提到的,我发现我必须扩展代理才能使用我的新 Operation 类。我唯一扩展的是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...
);
(如果我似乎在使用这种错误的方式或遗漏了文档中的某些内容,请告诉我。我会更乐意使用实现此功能的内置方法。)
【讨论】:
很好的发现。不要害羞,分享一些代码:)谁知道呢,也许有一天它会很有用。 @DmitryB 好的,我自己解释了 我认为您的用例与许多人所面对的相似。根据我的经验,如果模型上的 ID 属性是“int”类型,则默认代理在运行 sync() 时会做正确的事情。我曾经将我的 ID 属性设置为一个字符串,这会导致同步失败,如您所述。本质上,我的网格记录将始终显示“脏”标志,即使它们已同步到服务器。以上是关于使代理使用扩展的 Ext.data.Operation的主要内容,如果未能解决你的问题,请参考以下文章