在TypeScript中,我有一个围绕Web Storage API的包装类。为了使存储易于使用,我为应用程序需要存储的每个项初始化了一个类属性。下面是我的包装类(用TypeScript编写)
导出类 StorageService
get Storage(){return localStorage}
get testData(){return this.getItem('testData')}
set testData(val){this.setItem('testData',val)}
getItem(key:string){return JSON.parse(this.Storage.getItem(key))}
setItem(key:string, data:any){this.Storage.setItem(key, JSON.stringify(data))}
removeItem(key){this.Storage.removeItem(key)}
clear(){this.Storage.clear()}
在应用程序的其他地方,我想与对象testData
及其成员属性进行交互。以下工作正常:
storage.testData = {name:'Mary',age:6};
console.log(storage.testData); //initial object is retrieved
但是,如果我尝试更改testData的属性而不是设置整个对象,则永远不会调用setItem
方法,并且不会更改存储的内容。
storage.testData.age = 10;
console.log(storage.testData); //{name:'Mary',age:6} <- age was not changed
直观的解决方法是首先检索存储的对象,然后更新它,最后存储更新的值
var temp = storage.testData;
temp.age = 10;
storage.testData = temp;
console.log(storage.testData); //{name:'Mary',age:10} <- age is updated
这对小物体来说很好,但它不能很好地扩展。想象一下,testData有50或60个属性,而且在应用程序的多个点上,我只需更改其中的1个或2个。每次必须设置每个属性是没有意义的。无论如何,我可能无法更改应用程序的其余部分;我只提供存储接口。
我的问题是:我如何公开一种存储方法,允许直接设置/更改存储中对象的属性,而不是每次都要提供完整的对象存储?理想情况下,消费代码只需调用store.testData.age = value
来编辑当前存储的值。
PS:这也可能是针对另一个主题但是如果访问localStorage很多会真的减慢应用程序(根据下面的第1条评论),也许我没有使用Web存储,因为它的意图?也许我的包装器可以将值存储在内存中,但是可以按设定的间隔将它们全部存储起来。每3分钟说一次?我曾经严格在内存对象中反映应用程序的状态,但当用户导航或刷新页面时,所有对象都会丢失
答案 0 :(得分:0)
正如我在OP中提到的,我可能无法对界面进行更改。理想情况下,调用代码可以更改存储中对象的成员属性。我想我会尝试一种混合方法。将项目存储在内存中,但每个设置的间隔(或特定命令),将它们提交到存储。以下是我在TypeScript中的简化 StorageService
//push items to storage regularly
constructor() {this.restore();this.intervalID = setInterval(()=>this.commit(),this.COMMIT_INTERVAL*1000)}
Storage = window.localStorage;
COMMIT_INTERVAL = 60;//interval, in seconds, upon which changes are saved to storage
private intervalID:number;
private keys = ['testData', 'testData2']; //key names used set items in storage
//when data is accessed, return it from memory. If not there (eg after a page refresh), then from storage
private _testData = null;
public get testData(){return this._testData || this.getItem(this.keys[0])}
public set testData(val){this._testData = val} //we store in memory; not directly in storage until commit() is called.
//remove each value from memore and clear web storage
public clear(){
this.keys.forEach(key=>this['_'+key]=null,this);
this.Storage.clear()
}
// store memory data in web storage
public commit(){
this.keys.forEach(key => this.setItem(key,this['_'+key]),this);
}
//restore items from web storage. This is done in the constructor
private restore(){
this.keys.forEach(key => this[key] = this.getItem(key) || this[key])
}
//the methods that actually connect to storage are all private. Calling code must use commit() to interact with storage
private getItem(key:string){
return JSON.parse(this.Storage.getItem(key));
}
private removeItem(key){
this.Storage.removeItem(key);
}
private setItem(key:string, data:any){
this.Storage.setItem(key, JSON.stringify(data));
}
此服务允许调用代码使用的API保持不变:testData.age = 10
将更新内存中的对象,并最终(当调用commit()
时)。
请给我反馈。我不熟悉编码和厌倦了代价高昂的错误。