Sencha Touch - 本地存储问题

发布于 2025-01-06 19:24:51 字数 2131 浏览 3 评论 0原文

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

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

2)当我删除所有条目然后刷新页面时,我在控制台中收到此错误:“Uncaught TypeError:无法读取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();
      }

任何人都可以指出我做错的明显事情吗?

I'm having a few problems with Sencha Touch and localstorage...

1) I am able to save data into localstorage, and it works great until I refresh the page. After that point I can still access the data, appear to make changes, and even add new entries. But as soon as the page is refreshed, all of my updates are gone. Anything that was newly added will be fine, but updates to original entries will not be saved (hopefully this makes sense). Basically, I can create an entry and update it all I want until I refresh the page. At that point it will not save to localstorage again. New entries always save fine though.

2) When I delete all entries my entries and then refresh the page, I get this error in the console: "Uncaught TypeError: Cannot read property 'id' of null". It looks like it's trying to load something even though nothing is there. I'm not sure why it would throw an error in this situation and not when the page is originally loaded since it should be the same thing right?

Model:

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

Store:

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

Handler:

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

Can anyone point out something obvious that I'm doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

深府石板幽径 2025-01-13 19:24:51

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

模型:

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

I had the same issue and I moved my proxy into the model and this solved my problem. Your code modified should look like this:

Model:

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

Store:

Ext.regStore('inventoryItemsStore', {
    model: 'inventoryItem',
    sorters: [{
        property: 'id',
        direction: 'DESC'
    }],
    getGroupString: function (record) {
        return '';
    }
});
厌味 2025-01-13 19:24:51

事实证明,存储同步()对我来说非常棘手,这可能有助于阐明一些道理。

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

使用 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 的人来说,所有这些可能都是显而易见的,但对于像我这样的新手来说,这几乎需要一天的工作才能弄清楚。

希望这对某人有帮助,事实证明它将来也会对我有所帮助。

Store sync() has proven very tricky for me, this might help shed some light.

.sync() will not update the remote o localstorage records unless they are dirty. So they will not be persistent.

With a json type reader it's easy to make the mistake of directly modifying a record, one must use the Model's methods to do so, specifically .set(), because set() defines the record as “dirty” and only then sync() will actually save the changes.

This is particularly hard to debug using local storage.

For the following store:

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

Assuming you´ve populated the store with something like:

{'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'
                                                            ]
                                                        }
]
}

To fix the first's record misspelling you might be tempted to do the following:

{//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();
}
}

If you tried this there will be no errors on the console, so, all is ok. Right?

Wrong! The changes won't persist on restart. Why?

Because the records are “clean”.

How can we “dirty” them up?

The only way I found (I'm sure there are plenty more) is by using the method .set() from the Model to update the record, that'll tell the store it's dirty

That sounds odd to my untrained brain on MVC, better fixing the above example.

{//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();
}
}

All this might be obvious for someone coming from sencha touch 1, but for a newbie like me, it was close to a day's work to figure out.

Hope this helps someone, it will provably help me in the future.

爱的故事 2025-01-13 19:24:51

可能是别的东西。

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

我的印象是 id 由 localstorage API 在内部使用,因此被保留。

It probably is something else.

You are using “id” as a key name in the model fields, change that to something else like “inventory_id” and try again.

I'm under the impression that id is used internally by the localstorage API, so is reserved.

淡淡の花香 2025-01-13 19:24:51

我知道这个旧的,但也许它会对某人有所帮助。
我遇到了同样的问题,并尝试重置我的本地存储 window.localStorage.clear(); 并且它有效。

I know this old, but maybe it will help someone.
I had the same problem and try to reset my local storage window.localStorage.clear(); and it works.

七月上 2025-01-13 19:24:51

看起来一切都很好 - 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()
            }]
        });
    }
});

Seems all looks good - store.add() method is used in conjunction with store.sync(). Check the way how you load data into the list, may be the data just is not loaded. As for me, store's autoload property does not work always (may be there are some reasons, I don't negate), and I just use store.load() instead. Also, you may check localStorage directly to determine this definitely (i.e. proxy id item localStorage.getItem('inventory-app-store') should give you something like "1,2,3" - the ids of successfully persisted records).

Here is the working example, just in case.

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()
            }]
        });
    }
});
风吹雪碎 2025-01-13 19:24:51

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

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

How about you call sync() method before if-condition. It worked for me.

var inventoryStore = CostsApp.views.inventoryList.getStore();
inventoryStore.load();
inventoryStore.sync();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文