13

我想在 Ember.js 中使用 HTML5 本地存储。

如果没有 Ember Data,我找不到任何这样做的例子。

这应该怎么做?我需要考虑什么?

4

2 回答 2

23

因此,假设我们有一个对象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 特性”,称为Application.initializer初始化程序,它们是具有“名称”属性和一个initialize函数的简单类,您可以在其中访问您的应用程序container并执行需要完成的操作,让我在代码中解释一下:

为了在应用程序开始加载时得到通知,我们可以监听onLoad事件来创建我们的初始化类,这些类将registerinject前面提到的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 方式和一些虚构的延迟,而不仅仅是返回数组):

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

希望能帮助到你。

于 2013-08-30T11:04:35.527 回答
1

接受的答案很好,但我想我会添加这个替代方案:

Dan Gebhardt 创建了一个非常有趣的库,称为Orbit.js,用于协调客户端上的不同数据源。有三种开箱即用的数据源:内存、本地存储和 json api。

对于 ember 集成,请查看ember-orbit

它目前仍在大力开发中,并且引入了与Ember Data不同的范式,因此请谨慎行事!

于 2014-11-21T08:38:16.983 回答