我想在我的Ember.js中使用HTML5本地存储。
如果没有Ember Data,我无法找到任何这样做的例子。
应该怎么做?我需要考虑什么?
答案 0 :(得分:22)
因此,假设我们有一个名为Storage
的对象,在我们的实际实现中,它代表了localStorage
存储和检索数据的类似适配器的对象:
App.Storage = Ember.Object.extend({
init: function() {
this.clearStorage();
var items = ['foo', 'bar', 'baz'];
localStorage.items = JSON.stringify(items);
},
find: function(key) {
// pseudo implementation
if( !Ember.isNone(key) ) {
var items = [];
var storedItems = JSON.parse(localStorage[key]);
storedItems.forEach(function(item){
items.pushObject(item);
});
return items;
}
},
clearStorage: function() {
// pseudo implementation
localStorage.clear();
}
});
除了伪实现之外,你可以看到有一个虚拟数组,在对象初始化时存储了一些数据,稍后我们将在IndexRoute
model
钩子中使用它来检索它,只是为了显示这很有效。
现在更好的东西,你可以做register
&应用程序就绪后直接inject
,但是如果我们希望它在应用程序初始化时已经可用,该怎么办?好吧“有一个ember-feature for that”,名为Application.initializer
,初始化程序是简单的类,带有'name'属性和initialize
函数,您可以在其中访问您的应用程序container
和做任何需要做的事情,让我在代码中解释一下:
要在应用程序开始加载时收到通知,我们可以收听onLoad
事件,以创建我们的初始化程序类,将register
和inject
前面提到的Storage
对象转换为每个控制器和每条路线:
Ember.onLoad('Ember.Application', function(Application) {
// Initializer for registering the Storage Object
Application.initializer({
name: "registerStorage",
initialize: function(container, application) {
application.register('storage:main', application.Storage, {singleton: true});
}
});
// Initializer for injecting the Storage Object
Application.initializer({
name: "injectStorage",
initialize: function(container, application) {
application.inject('controller', 'storage', 'storage:main');
application.inject('route', 'storage', 'storage:main');
}
});
});
现在,由于Storage
对象被注入到每个路由和每个控制器中,我们终于可以在IndexRoute
model
挂钩中访问它,并使上面提到的存储数组可用调用self.get('storage').find('items')
到我们要呈现的模板(只是添加了一个承诺,使它实际上符合ember-way和一些虚拟延迟,而不仅仅是返回数组):
App.IndexRoute = Ember.Route.extend({
model: function(){
var self = this;
var promise = new Ember.RSVP.Promise(function(resolve) {
Ember.run.later(function() {
var data = self.get('storage').find('items');
console.log(data);
resolve(data);
}, 1000);
});
return promise;
}
});
在我们的index
模板中,我们现在可以疯狂地遍历虚拟阵列而不关心它来自哪里:
<script type="text/x-handlebars" id="index">
<h2>Index</h2>
<ul>
{{#each item in model}}
<li>Item: {{item}}</li>
{{/each}}
</ul>
</script>
最后,您可以在一个工作示例中看到以上所有内容:http://jsbin.com/eqAfeP/2/edit
希望它有所帮助。
答案 1 :(得分:1)
接受的答案很棒,但我想我会添加这个替代方案:
Dan Gebhardt创建了一个非常有趣的库Orbit.js,用于协调客户端上的不同数据源。有三个开箱即用的数据源:内存,本地存储和json api。
对于ember集成,请查看ember-orbit。
此时它仍处于重大发展阶段,它引入了与Ember Data不同的范例,所以请谨慎行事!