Мне нужно было обновить некоторые данные модели, которые пришли с сервера. В настоящее время есть два варианта: вызвать Model.set
или установить Model.attributes
напрямую. Я не хотел, чтобы изменения записывались, но я также не мог использовать silent
потому что мне нужно было обновить соответствующие представления. Итак, я написал патч обезьяны:
Backbone.Model.prototype.reset = (attributes, options) ->
attrs = attributes || {};
if options.parse
attrs = this.parse(attrs, options) || {}
@set(attrs, options);
<strong i="9">@changed</strong> = {};
Интересно, почему Backbone.Model
не имеет такого метода сброса, как Backbone.Collection
?
Reset - это аварийный выход, который позволяет вам легко выполнять эффективный массовый рендеринг, когда вы знаете, что вам это нужно.
В вашем случае просто используйте set
.
Можно ли установить, не делая изменений атрибутов грязными?
1 августа 2014 г. в 7:28 Джереми Ашкенас [email protected] написал:
Reset - это аварийный выход, который позволяет вам легко выполнять эффективный массовый рендеринг, когда вы знаете, что вам это нужно.
В вашем случае просто используйте set.
-
Ответьте на это письмо напрямую или просмотрите его на GitHub.
Вызов Model.clear()
до Model.set({})
будет работать в вашем случае? Таким образом, вы не будете расширять текущие атрибуты, вместо этого они будут заменены. Model.clear()
также поддерживает тихую опцию, если вы не хотите запускать два события «изменения» в модели.
Я согласен, что этот метод отсутствует. Я также подумал об использовании model.clear()
и model.set()
вместе. Затем я столкнулся с проблемой: я дважды запускаю событие change
.
Использование опции silent
при вызове model.clear()
не является вариантом, потому что я также хочу, чтобы событие change
запускалось, когда свойство сбрасывается.
Метод model.reset()
принимает новый хэш атрибутов и заполняет этот хэш значениями undefined
для ключей старых атрибутов, отсутствующих в новом хеш-атрибуте.
Model.prototype.reset = function(attrs, options) {
for (var key in this.attributes) {
if (key in attrs) continue;
attrs[key] = void 0;
}
return this.set(attrs, options);
};
@lennerd
Что о:
Model.prototype.reset = function(attrs, options) {
for (var key in this.attributes) {
this.unset(key, {silent:true});
}
return this.set(attrs, options);
};
Нет, это не поможет. Представьте, что у вас есть ключ foo
в текущем хэше атрибутов модели, которого нет в новом хэше attrs
вы передаете model.reset()
. Когда я слушаю событие change:foo
, оно не запускается с новым значением undefined
, потому что мы использовали model.unset()
в тихом режиме.
Backbone.Model.prototype.reset = function(attrs, options) {
for (var key in this.attributes) {
this.unset(key, {silent:true});
}
return this.set(attrs, options);
};
var bar = new Backbone.Model();
bar.on('change', function(model) {
console.log('The model bar has been changed.');
});
bar.on('change:foo', function(model, foo) {
console.log('Foo has been changed to: ' + foo);
});
bar.set(foo, 'test');
// => The model bar has been changed.
// => Foo has been changed to: test
bar.reset({ foo2: 'test2' });
// => The model bar has been changed.
// Foo was resetted but no change event has been triggered.
Круто, я понял, о чем ты. Я бы, вероятно, предпочел использовать this.unset(key, options)
вместо явного переопределения this.attributes, но это просто вопрос замены attrs[key] = void 0;
: panda_face:
Прошу прощения за проявленное мной невежество, поскольку я все еще относительно новичок в backbone.js, но обсуждаемое поведение звучит как Model.fetch
. В описании сказано:
Сбрасывает состояние модели с сервера
Похоже, что события change
все еще запускаются, но не делают модель «грязной». Есть ли причина, по которой этот подход не может быть применен, когда вы хотите сбросить атрибуты на основе ответа сервера? Я предполагаю, что такая ситуация может возникнуть только тогда, когда модель изменяется как побочный эффект другой операции, но обычно такие побочные эффекты считаются плохим программированием, и их следует по возможности избегать. Если побочного эффекта нельзя избежать, возможно, имеет смысл отправить флаг ответа «обновить модель XYZ» вместо атрибутов новой модели и вызвать fetch
всякий раз, когда вы видите такой ответ.
Опять же, прошу прощения за любое невежество, которое я проявляю в этом комментарии.
@kolorahl ,
OP хочет очистить текущие атрибуты модели и передать новый JSON, который станет новыми атрибутами модели. Таким образом, мы действительно не хотим задействовать серверную часть, если у нас уже есть JSON.
Я как-то согласен с @ lupugabriel1 с его методом clear + set. Но я думаю, что это одна из функций, которую необходимо учитывать. Что-то вроде Backbone.Collection # reset
Причина, по которой мне это было нужно, в том, что мир меняется. Backbone предполагает, что Model # fetch () XHR является основным методом загрузки данных с сервера, но мы делаем гораздо больше, используя веб-сокеты. Когда данные передаются клиенту, вызывать .fetch излишне, и нам нужен приличный способ загрузки неопубликованных данных и при этом запускать обработчик событий.
Почему вы не используете #set
?
@jridgewell, потому что
function callback(data_from_server) {
console.info(data_from_server);
m = new Backbone.Model(data_from_server);
m.set('foo', 'what?', {silent: true});
console.info(m.changedAttributes())
}
Фактический результат:
{foo: 'bar'}
{foo: "what?"}
Желаемый результат:
{foo: 'bar'}
false
Set подходит для случаев, когда состояние изменилось вне синхронизации с сервером, но требуется сброс Model #, потому что нет возможности пометить состояние как синхронизируемое с сервером.
В итоге я написал другой патч для этой функции:
/**
* Allow for side-loading data from the server, calling the sync event afterwards.
* <strong i="6">@param</strong> attributes
* <strong i="7">@param</strong> options
*/
Backbone.Model.prototype.sync_set = function(attributes, options) {
var attrs = attributes || {};
if (options.parse) {
attrs = this.parse(attrs, options) || {}
}
this.set(attrs, options);
this.changed = {};
this.trigger('sync', this, attributes, options);
return this;
}
function callback(data_from_server) {
console.info(data_from_server);
m = new Backbone.Model(data_from_server);
m.set('foo', 'what?', {silent: true});
console.info(m.changedAttributes())
}
{foo: 'bar'}
false
Вероятно, это также должно отключить недостающие элементы. Не уверен, что Model # set (attributes) делает это.
Как отметил @lennerd , вызов clear()
последующим set()
не является хорошим вариантом, потому что он
1) Запускает два события change
и
2) Если вы используете silent:true
вызова clear
, вы не получите событий изменения для атрибутов, которые не были установлены.
collection.reset()
очень интуитивно понятен, и я думаю, что Model
действительно может выиграть от эквивалентного метода. Я все время пытаюсь использовать model.reset(attrs)
, всегда разочаровываюсь, когда этого нет. :(
Я пошел дальше и создал небольшое расширение, чтобы добавить рабочий метод reset
в Backbone.Model: Backbone-Model-Reset
Согласитесь - полезно было бы иметь родную. Мне нужно было просто сбросить атрибуты, не изменяя атрибут id, как это делал clear (). Вот его суть .
@thesmart , Model # set не сбрасывает недостающие атрибуты, поэтому я считаю, что сброс Model # необходим.
При закрытии вопроса необходимо указать причину. Я хотел бы знать, почему @ akre54 закрыл это. Базовые модели намеренно примитивны и лишены мнений, однако отсутствие сброса Model # выражает мнение о том, как используются модели. С http://backbonejs.org/#Getting -started
С философской точки зрения Backbone - это попытка обнаружить минимальный набор примитивов структурирования данных (модели и коллекции) и пользовательского интерфейса (представления и URL-адреса), которые обычно полезны при создании веб-приложений с помощью JavaScript.
Насколько я могу судить, модель данных Backbone несовместима с REST.
потому что нет возможности безопасно смоделировать состояние сервера на клиенте после
Модель построена. Построение новой модели - единственный способ получить
свежее состояние без перезагрузки.
Во вторник, 5 июля 2016 г., pgifford [email protected] написал:
@thesmart https://github.com/thesmart , номер модели не отменяется, отсутствует
атрибуты, поэтому я считаю, что сброс Model # необходим.При закрытии вопроса необходимо указать причину. Я бы
хотел бы знать, почему @ akre54 https://github.com/akre54 закрыл это.
Магистральные модели намеренно примитивны и лишены мнений, однако
отсутствие Model # reset выражает мнение о том, как используются модели. Из
http://backbonejs.org/#Getting -startedС философской точки зрения Backbone - это попытка открыть минимальный набор
структурирование данных (модели и коллекции) и пользовательский интерфейс (представления и
URL-адреса) примитивы, которые обычно полезны при создании веб-приложений.
с JavaScript.-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/jashkenas/backbone/issues/3253#issuecomment -230586424,
или отключить поток
https://github.com/notifications/unsubscribe/AARJLQ8-BGeV0X_owHVpyPQAdeiMweNMks5qSriDgaJpZM4CTBHH
.
Мне нужна была модель reset
и я сделал ее в _spirit_ Backbone. Я использую это в своем личном расширении Backbone.
Это лучше, чем простой .clear
за которым следует .set
потому что он объединяет значения по умолчанию обратно в модель, позволяя любым переданным атрибутам переопределять их, как при инициализации.
/**
* Clears the model's attributes and sets the default attributes.
* <strong i="10">@param</strong> {Object} attributes to overwrite defaults
* <strong i="11">@param</strong> {Object} options to pass with the "set" call.
* <strong i="12">@return</strong> {Backbone.Model} this object, to chain function calls.
*/
reset: function(attributes, options) {
options = _.extend({ reset: true }, options);
// ensure default params
var defaults = _.result(this, 'defaults'),
attrs = _.defaults(_.extend({}, defaults, attributes || {}), defaults);
// apply
this._reset(attrs, options);
// triggers a custom event, namespaced to model in order
// to avoid collision with collection's native reset event
// when listening to a collection.
if (!options.silent) this.trigger('model:reset', this, options);
return this;
},
/**
* Private method to help wrap reset with a custom behavior in child
* classes.
* <strong i="13">@param</strong> {Object} attributes to overwrite defaults
* <strong i="14">@param</strong> {Object} options to pass with the "set" call.
*/
_reset: function(attrs, options) {
this.clear({ silent: true }).set(attrs, options);
},
Он запускает события изменения ( change
и change:attribute
) в дополнение к пользовательскому событию model:reset
если не silent: true
. Его можно легко настроить для запуска только события model:reset
но я думаю, что события изменения всегда должны запускаться при сбросе модели.
Я немного изменил решение lennerd https://github.com/jashkenas/backbone/issues/3253#issuecomment -58789524.
Backbone.Model.prototype.reset = function(attrs, options) {
var missing = {};
for (var key in this.attributes) {
if (key in attrs) continue;
attrs[key] = undefined;
missing[key] = true;
}
// trigger all change events at the same time
this.set(attrs, options);
// remove missing attributes completely
for (var key in missing) {
// no silent option here in case attributes changed again meanwhile (edge case)
this.unset(key)
}
return this;
};
Самый полезный комментарий
@thesmart , Model # set не сбрасывает недостающие атрибуты, поэтому я считаю, что сброс Model # необходим.
При закрытии вопроса необходимо указать причину. Я хотел бы знать, почему @ akre54 закрыл это. Базовые модели намеренно примитивны и лишены мнений, однако отсутствие сброса Model # выражает мнение о том, как используются модели. С http://backbonejs.org/#Getting -started