Подтвердить что ты не робот

Как получить доступ к вычисленному полю базовой модели из шаблона руля?

Я хотел бы получить доступ к рассчитанным полям, которые я реализовал в модели (backbone.js) из шаблона. Нужно ли всегда определять помощника, чтобы сделать это?

Я думаю, что проблема связана с тем, как я передаю модель шаблону. Если я передаю this.model.toJSON(), у меня есть доступ к свойствам, но не к функциям, которые я определил в нем. Если я передам this.model напрямую, я могу получить доступ к функции, но не к свойствам базовой модели.

4b9b3361

Ответ 1

Всегда передавайте this.model.toJSON() в свои шаблоны.

Что вам нужно сделать, чтобы получить рассчитанные значения, переопределяет ваш метод toJSON на вашей модели.


MyModel = Backbone.Model.extend({

  myValue: function(){
    return "this is a calculated value";
  },

  toJSON: function(){
    // get the standard json for the object
    var json = Backbone.Model.prototype.toJSON.apply(this, arguments);

    // get the calculated value
    json.myValue = this.myValue();

    // send it all back
    return json;
  }

})

И теперь у вас есть доступ к myValue из JSON, который возвращается toJSON, что означает, что у вас есть доступ к нему в представлении.

Другой вариант, как вы упомянули, заключается в создании вспомогательных методов и регистрации их с помощью Handlebars. Если у вас нет какой-либо функциональности, которая изменяется в зависимости от способа визуализации шаблона и/или того, какие данные передаются в шаблон, я бы не стал этого беспокоиться.

Ответ 2

Вот еще одна возможность: (из инициализации модели)

initialize: function() {
        this.on("change", function () {
            this.set({ calculatedColumn: this.get("otherColumn") }, { silent: true });
        });
    },

Вычисляемые свойства в Backbone

Ответ 3

У меня была такая же проблема. @DerickBailey прав, конечно, что переопределение в JSON делает эту работу. Но он также течет в связи с сервером (см. Комментарий muu на его ответ).

Итак, в конце концов, я построил плагин Backbone, чтобы специально обрабатывать экспорт данных в шаблоны, и делаю это с минимумом суеты: Backbone.Marionette.Export. Он также имеет дело с вложенными структурами, заботится о циклических ссылках и т.д. См. docs.

Вот как это работает. Включите файл плагина в свой проект и объявите

MyModel = Backbone.Model.extend({

  foo: function () {
      return "I am a calculated value";
  },

  exportable: "foo"    // <-- this is the one line you have to add

});

Если вы являетесь пользователем Marionette, вы уже сделали это. foo отображается в ваших шаблонах, как если бы это был атрибут модели.

В простых представлениях Backbone просто вызовите myModel.export() или myCollection.export() вместо своих toJSON-копий при рендеринге.

Для методов, принимающих аргументы, существует обработчик onExport. Примеры, опять же, находятся в docs.

Ответ 4

Лучший способ сделать это - добавить это в свою модель:

function initialize() {
    this.set("calculatedColumn", function () { return this.otherColumn; });
}

В базовой модели обычно хранятся фактические значения данных внутри "model.attributes". Поэтому, когда вы передаете свою модель непосредственно в шаблон, у нее есть только функции, добавленные непосредственно к модели, а не к каким-либо данным. И если вы используете model.toJSON(), он обычно реализуется в магистрали как _.clone(model.attributes) (см. Backbone.js). Таким образом, у вас есть данные, а не функции, добавленные непосредственно в модель. Вот почему вышеизложенное работает - вы устанавливаете функцию на model.attributes, а не на сам объект модели. Не ссылайтесь непосредственно на model.attributes, используйте model.get( "calculateColumn" ) и model.set( "calculateColumn" ,...).

Итак, model.get( "calculateColumn" ) возвращает функцию. Если вы перейдете {{calcColumn}} в дескрипторы (при условии, что вы используете рули), это показывает значение, возвращаемое функцией. Но calculateColumn не будет отправлен на сервер, потому что хост делает JSON.stringify для model.toJSON в синхронизации (в backbone.js) и JSON.stringify игнорирует функции. Если вы хотите, чтобы JSON.stringify не игнорировал функцию (поэтому функция превращается в значение данных всякий раз, когда toJSON запускается в модели - во время рендеринга представления и синхронизации модели) переопределяет model.toJSON так же, как описано @Derick Bailey.

Кроме того, вы можете получить свой собственный BaseModel с Backbone.Model и переопределить .toJSON и получить все ваши модели из BaseModel, если вам нужно. Тогда вам понадобится общая версия .toJSON, которая может быть применена к любой модели.