Sencha Touch - 本地存储问题

Posted

技术标签:

【中文标题】Sencha Touch - 本地存储问题【英文标题】:Sencha Touch - localstorage problems 【发布时间】:2012-02-17 02:28:11 【问题描述】:

我在使用 Sencha Touch 和 localstorage 时遇到了一些问题...

1) 我能够将数据保存到本地存储中,并且在我刷新页面之前效果很好。在那之后,我仍然可以访问数据,进行更改,甚至添加新条目。但是一旦页面被刷新,我所有的更新都消失了。新添加的任何内容都可以,但不会保存对原始条目的更新(希望这是有道理的)。基本上,我可以创建一个条目并根据需要更新它,直到我刷新页面。那时它不会再次保存到本地存储。不过,新条目总是保存得很好。

2) 当我删除我的所有条目然后刷新页面时,我在控制台中收到此错误:“未捕获的类型错误:无法读取 null 的属性 'id'”。看起来它正在尝试加载一些东西,即使那里什么也没有。我不确定为什么它会在这种情况下引发错误,而不是在页面最初加载时引发错误,因为它应该是同一件事吧?

型号:

    Ext.regModel('inventoryItem', 
        idProperty: 'id',
        fields: [
             name: 'id', type: 'int' ,
             name: 'date', type: 'date', dateFormat: 'c' ,
             name: 'title', type: 'string' ,
             name: 'quantity', type: 'int' ,
             name: 'size', type: 'int' ,
             name: 'cost', type: 'double' ,
             name: 'startDate', type: 'date' ,
             name: 'endDate', type: 'date' ,
             name: 'dailyAvgCost', type: 'string' ,
             name: 'dailyAvgSize', type: 'string' 
        ]
    );

商店:

    Ext.regStore('inventoryItemsStore', 
        model: 'inventoryItem',
        sorters: [
            property: 'id',
            direction: 'DESC'
        ],
        proxy: 
            type: 'localstorage',
            id: 'inventory-app-store'
        ,
        getGroupString: function (record) 
            return '';
        
    );

处理程序:

     
             var currentinventoryItem = CostsApp.views.inventoryEditor.getRecord();
             CostsApp.views.inventoryEditor.updateRecord(currentinventoryItem);
             var inventoryStore = CostsApp.views.inventoryList.getStore();
             if (null == inventoryStore.findRecord('id', currentinventoryItem.data.id))
             
                     inventoryStore.add(currentinventoryItem);
             

             inventoryStore.sync();
             inventoryStore.sort([ property: 'date', direction: 'DESC']);
             CostsApp.views.inventoryList.refresh();
      

谁能指出我做错了什么明显的事情?

【问题讨论】:

什么 CostsApp.views.inventoryEditor.updateRecord(currentinventoryItem);做?听起来您的模型不知道他们出于某种原因已被编辑过。 【参考方案1】:

我遇到了同样的问题,我将代理移到模型中,这解决了我的问题。您修改后的代码应如下所示:

型号:

Ext.regModel('inventoryItem', 
    idProperty: 'id',
    fields: [
         name: 'id', type: 'int' ,
         name: 'date', type: 'date', dateFormat: 'c' ,
         name: 'title', type: 'string' ,
         name: 'quantity', type: 'int' ,
         name: 'size', type: 'int' ,
         name: 'cost', type: 'double' ,
         name: 'startDate', type: 'date' ,
         name: 'endDate', type: 'date' ,
         name: 'dailyAvgCost', type: 'string' ,
         name: 'dailyAvgSize', type: 'string' 
    ],
proxy: new Ext.data.LocalStorageProxy(
    id: 'inventory-app-store'
)
);

商店:

Ext.regStore('inventoryItemsStore', 
    model: 'inventoryItem',
    sorters: [
        property: 'id',
        direction: 'DESC'
    ],
    getGroupString: function (record) 
        return '';
    
);

【讨论】:

【参考方案2】:

事实证明,Store sync() 对我来说非常棘手,这可能会有所帮助。

.sync() 不会更新远程 o 本地存储记录,除非它们是脏的。所以他们不会坚持下去。

使用json类型的阅读器很容易犯直接修改记录的错误,必须使用模型的方法来这样做,特别是.set(),因为set()将记录定义为“脏”,只有这样 sync() 才会真正保存更改。

使用本地存储特别难以调试。

对于以下商店:

Ext.define('MyApp.store.LocalStuff',
extend: 'Ext.data.Store',
xtype:'localstuff',

config: 
    fields:['stuffId','stuffName','stuffArray'],
    storeId:'LocalStuffId',
    autoLoad:false,
    proxy:
        type:'localstorage',
        id:'idForLocalStorage',
        reader: 
            type: 'json',
            rootProperty: 'stuffArray'
        
    

);

假设您已经在商店中填充了以下内容:

'stuffArray':[
'stuffId':'130',   'stuffName':'floob',    'stuffArray':[  
                                                            'first',
                                                            'second',
                                                            'tird' //here be a typo (on purpose)
                                                            ]
                                                        ,
'stuffId':'131',   'stuffName':'sateo',    'stuffArray':[  
                                                            'primero',
                                                            'segundo',
                                                            'tercero'
                                                            ]
                                                        ,
'stuffId':'133',   'stuffName':'tolus',    'stuffArray':[  
                                                            'prima',
                                                            'secunda',
                                                            'tertia'
                                                            ]
                                                        
]

要修复第一个记录的拼写错误,您可能会尝试执行以下操作:

//in a given controller or view
someEventHandler:function()
    var stor = Ext.getStore('LocalStuffId');
    var firstRecord = stor.getAt(0);//which will get you a record in the form of a Model
    firstRecord.get('stuffArray')[2]='third';//that will fix it
    //now we just sync() to make the change persist when we close the app
    stor.sync();


如果您尝试过,控制台上不会出现错误,所以一切正常。对吧?

错了!重新启动时更改不会持续存在。为什么?

因为记录是“干净的”。

我们怎样才能“弄脏”它们?

我发现的唯一方法(我相信还有更多)是使用模型中的方法 .set() 来更新记录,这会告诉商店它很脏

这对我未经训练的 MVC 大脑来说听起来很奇怪,最好修复上面的例子。

//in a given controller or view
someEventHandler:function()
    var stor = Ext.getStore('LocalStuffId');
    var firstRecord = stor.getAt(0);//which will get you a record in the form of a Model
    //you might go around the following 2 lines in many ways, the important part is .set() after that
    var theArrayToFix = firstRecord.get('stuffArray');
    theArrayToFix[2]='third';

    firstRecord.set('stuffArray',theArrayToFix);//set() dirties the record
    //NOW we sync() to make the change persist when we close the app
    stor.sync();


所有这些对于来自 sencha touch 1 的人来说可能是显而易见的,但对于像我这样的新手来说,这几乎是一天的工作才能弄清楚。

希望这对某人有所帮助,它会在未来证明对我有所帮助。

【讨论】:

【参考方案3】:

这可能是别的东西。

您在模型字段中使用“id”作为键名,将其更改为“inventory_id”之类的其他名称,然后重试。

我的印象是 id 是 localstorage API 在内部使用的,所以是保留的。

【讨论】:

【参考方案4】:

我知道这个老了,但也许它会帮助别人。 我遇到了同样的问题并尝试重置我的本地存储window.localStorage.clear(); 并且它可以工作。

【讨论】:

【参考方案5】:

看起来一切都很好 - store.add() 方法与 store.sync() 结合使用。检查您如何将数据加载到列表中的方式,可能是数据没有加载。至于我,store的autoload属性并不总是有效(可能有一些原因,我不否定),我只是用store.load()代替。此外,您可以直接检查localStorage 以确定这一点(即代理ID 项localStorage.getItem('inventory-app-store') 应该给您类似"1,2,3" - 成功持久记录的ID)。

这是一个工作示例,以防万一。

new Ext.Application(
    name: 'MyApp',
    launch: function() 
        this.viewport = new Ext.Panel(
            fullscreen: true,
            id    : 'mainPanel',
            layout: 'card',
            dockedItems: [
                xtype: 'toolbar',
                dock : 'top',
                items: [
                    xtype: 'textfield',
                    flex: 1
                , 
                    text: 'Add',
                    listeners: 
                        tap: function () 
                            var view = this.viewport,
                                list = view.items.first(),
                                store = list.store,
                                fld = view.dockedItems.first().items.first(),
                                val = fld.getValue();
                            store.add(item: val);
                            store.sync();
                            fld.reset();
                        ,
                        scope: this
                    
                ]
            ],
            items : [
                xtype: 'list',
                itemTpl : 'item',
                store: new Ext.data.Store(
                    fields: ['item'],
                    proxy: 
                        id: 'items',
                        type: 'localstorage',
                    
                ).load()
            ]
        );
    
);

【讨论】:

【参考方案6】:

在 if 条件之前调用 sync() 方法怎么样。它对我有用。

var inventoryStore = CostsApp.views.inventoryList.getStore();
inventoryStore.load();
inventoryStore.sync();

【讨论】:

以上是关于Sencha Touch - 本地存储问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Sencha Touch 中的商店之间同步

sencha 中的本地存储

Sencha Touch 2 + PhoneGap + iPad:带有base64编码数据的视频:“操作无法完成”

如何单独使用 Sencha touch 2 访问原生 iOS 文件系统

Sencha Touch 同步并从服务器获取新数据

如何在 Sencha Touch 2 模型中存储日期