Магистраль: синхронизация моделей и LocalStorage

Я расширил модель A и коллекцию As следующим образом:

define(['underscore', 'backbone', 'backbone.localStorage'], function(_, Backbone) {
   var A = Backbone.Model.extend({
      initialize: function() {          
      }
   });

   var A_Collection = Backbone.Collection.extend({
      model: A,
      localStorage: new Backbone.LocalStorage("as")
   });

   return {
      Model: A,
      Collection: A_Collection 
   };
});

Коллекции хранятся в localStorage, и все отлично работает в моем приложении. Затем я очищаю и заменяю localStorage непосредственно кодом (используя функции clear и setItem) и пытаюсь создать новую коллекцию, но изменения не обнаруживаются:

var aux = new A.Collection();
aux.fetch(); 
// aux is empty

В противном случае, если попытаться:

var aux = new A.Collection();
aux.localStorage = new Backbone.LocalStorage("as");
aux.fetch(); 
// aux contains new data 

Последнее не подходит для меня, потому что мне придется изменить все создание коллекций в моем проекте.

Что мне не хватает?

1 ответ

Решение

Экземпляры Backbone.LocalStorage не предназначены для прослушивания LocalStorage изменения, которые происходят вне их собственного кода. Вот почему вы получаете поведение, которое вы получаете. Тем не менее, есть обходной путь.

Когда вы определяете коллекцию следующим образом:

var A_Collection = Backbone.Collection.extend({
   model: A,
   localStorage: new Backbone.LocalStorage("as")
});

localStorage значение разделяется всеми экземплярами A_Collection, Вы можете автоматически создать новый экземпляр Backbone.LocalStorage, как это:

var A_Collection = Backbone.Collection.extend({
  model: A,
  initialize: function() {
    A_Collection.__super__.initialize.apply(this, arguments);
    A_Collection.prototype.localStorage = new Backbone.LocalStorage("as");
  },
});

Мы должны установить его на прототип, чтобы он использовался всеми экземплярами A_Collection, что такое же поведение, как ваш исходный код. Имея это в виду, всякий раз, когда вы создаете новый экземпляр A_Collection, вы получите новый экземпляр Backbone.LocalStorage, который будет получать информацию заново от LocalStorage,

Вот иллюстрация плунжера. Вот соответствующий код для справки:

var A = Backbone.Model.extend({
  initialize: function() {}
});

var A_Collection = Backbone.Collection.extend({
  model: A,
  initialize: function() {
    A_Collection.__super__.initialize.apply(this, arguments);
    A_Collection.prototype.localStorage = new Backbone.LocalStorage("as");
  },
});

// Setup a collection.
var collection = new A_Collection();
collection.fetch();

// Clean it out from previous runs... Note that we have to use destroy to destroy all items. 
// Reset won't save to LocalStorage.
while (collection.length > 0) {
  var model = collection.at(0);
  model.destroy();
  collection.remove(model);
}
// and set some elements.
collection.create({
  name: "1"
});
collection.create({
  name: "2"
});
console.log("collection length:", collection.length);

// Mess with it outside the Backbone code.
localStorage.clear();
// Manually create data that looks like what Backbone expects.
localStorage.setItem("as-1", JSON.stringify({
  name: "foo",
  id: "1"
}));
localStorage.setItem("as-2", JSON.stringify({
  name: "bar",
  id: "2"
}));
localStorage.setItem("as-3", JSON.stringify({
  name: "baz",
  id: "3"
}));
localStorage.setItem("as", "1,2,3");

// Create a new collection that loads from LocalStorage
var collection2 = new A_Collection();
collection2.fetch();
console.log("collection 2 length:", collection2.length);
console.log("first item", collection2.at(0).toJSON());
console.log("third item", collection2.at(2).toJSON());

console.log("instance is shared?", collection.localStorage === collection2.localStorage);

Код выше генерирует это на консоли:

collection length: 2
collection 2 length: 3
first item Object {name: "foo", id: "1"}
third item Object {name: "baz", id: "3"}
instance is shared? true
Другие вопросы по тегам