Backbone: Добавьте в Backbone.Model метод "сброса"

Созданный на 31 июл. 2014  ·  22Комментарии  ·  Источник: jashkenas/backbone

Мне нужно было обновить некоторые данные модели, которые пришли с сервера. В настоящее время есть два варианта: вызвать 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 ?

question

Самый полезный комментарий

@thesmart , Model # set не сбрасывает недостающие атрибуты, поэтому я считаю, что сброс Model # необходим.

При закрытии вопроса необходимо указать причину. Я хотел бы знать, почему @ akre54 закрыл это. Базовые модели намеренно примитивны и лишены мнений, однако отсутствие сброса Model # выражает мнение о том, как используются модели. С http://backbonejs.org/#Getting -started

С философской точки зрения Backbone - это попытка обнаружить минимальный набор примитивов структурирования данных (модели и коллекции) и пользовательского интерфейса (представления и URL-адреса), которые обычно полезны при создании веб-приложений с помощью JavaScript.

Все 22 Комментарий

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.

http://jsfiddle.net/lennerd/3s1Ltwgu/

Круто, я понял, о чем ты. Я бы, вероятно, предпочел использовать 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;
};
Была ли эта страница полезной?
0 / 5 - 0 рейтинги