Массивы Javascript и Метеорная сессия

Я сделал интересное наблюдение. При попытке обновления массива, хранящегося в хранилище сеансов Meteor, следующий код не будет распространять изменения:

var tags = Session.get("Tags");
tags.push("a");
Session.set("Tags", tags);

Но если я изменил первую строку на использование Session.get("Tags").slice(), все, что зависит от сеанса, будет соответствующим образом обновляться. Я предполагаю, что это связано с тем, что Meteor проверяет некоторые ссылки на равенство и, следовательно, ничего не обновляет.

Есть ли лучший способ управлять списками, хранящимися в хранилище сеансов метеоритов?

Если я сейчас попытаюсь удалить элемент из коллекции (используя array.remove() из здесь), поведение оказывается немного... из... Я делаю это внутри события шаблона Meteor, код выглядит следующим образом:

"click .taglist li" : function(e) {
  var tags = Session.get("Tags").slice();
  var index = cardTags.indexOf(this);

  Meteor._debug(Session.get("Tags").slice().indexOf("a"));
  Meteor._debug("Removing tag \"" + this + "\", index: " + index, ", typeof(this) = " + typeof(this).toString());

  tags.remove(index);
  Session.set("Tags", tags);
}

Выводится:

1
Removing tag "a", index: -1, typeof(this) = string

Итак, как-то оператор cardTags.indexOf(this);, кажется, возвращает -1 практически для любого случая. Я думаю, что я делаю что-то принципиально неправильное, так как теперь я достаточно разбираюсь в javascript, но почему-то не могу понять, что происходит здесь.

Почему эти два вызова indexOf() ведут себя иначе?

Ответ 1

Я считаю, что это так же, как эта ситуация в Backbone.js. Чтобы инициировать событие изменения, Meteor должен иметь новую ссылку для массива, а не только обновленную копию старого.

Вкратце, чтобы иметь "правильное" поведение, вам нужно клонировать массив, вносить нужные изменения, а затем выполнять Session.set('foo', myCopiedArray).

Ответ 2

Короче: Вместо этого используйте var index = cardTags.indexOf(this.toString());.

Длинная версия:

При использовании строк в JavaScript это строки, тогда как typeof 'test' возвращает string.

Посмотрим на следующий код, чтобы узнать другой способ представления строк в JavaScript:

var func = function () {
    return this;
};
console.log(func.call('test'));

Консоль (по крайней мере, FireBug) не покажет нам "test", но вместо этого отобразит String {0="t", 1="e", 2="s", 3="t" }. typeof вернет "object".

Содержимое оператора this, по-видимому, должно быть объектом. Чтобы преобразовать строку в объект "String", мы можем сделать console.log(new String('test'));, что совпадает с ранее зарегистрированным значением.

Чтобы преобразовать строковый объект в строку (тип данных), просто используйте его прототип toString.