Магистраль: использование данных модели и функций в представлении

Я новичок в Backbone и задавался вопросом, как получить доступ к данным модели и функциям из представления, которое вводит модель в зависимость.

Моя модель выглядит так:

countries.coffee

define [
  'underscore'
  'backbone'
  'parse'
], (_, Backbone, Parse) ->
  'use strict';

  class CountriesModel extends Parse.Object

    countries: ['GB','US','FR','JP','WL','ZM','NG']

    returnCode = (code) ->
      return code

И мой взгляд выглядит так:

country.coffee

define [
  'jquery'
  'underscore'
  'backbone'
  'templates'
  'models/projects'
  'models/countries'
], ($, _, Backbone, JST, CountriesModel, ProjectModel) ->
  class CountryView extends Backbone.View

    ...

    console.log countries

    returnCode(4)

Я вставляю CountriesModel в качестве зависимости, но когда я вызываю функцию или регистрирую countries, я получаю следующую ошибку:

Uncaught ReferenceError: returnCode is not defined

Я не могу понять, что я делаю неправильно. Любая помощь приветствуется. Спасибо заранее!

UPDATE

Ive обновил код выше, чтобы предоставить немного больше контекста.

Я пытаюсь создать повторно используемую модель (CountriesModel), поэтому я могу получить доступ к этому массиву countries и функции returnCode для разных представлений в моем приложении. Но я не могу понять, как получить доступ к ним на моем CountryView.

My CountryView уже требует модель ProjectModel, а Im способен вызывать функции и массивы из ProjectModel следующим образом:

this.model.exampleArray
 this.model.exampleFunction()

Я не могу понять, как я вызываю функции или массивы из своего CountriesModel.

Кто-нибудь знает, что я делаю неправильно?

Ответ 1

Я думаю, что в этом конкретном случае было бы полезно создать модель "countryModel" и базовую коллекцию "countriesCollection". Но это может быть не характер вашего вопроса (ваше обновление указывает, что вы боретесь с возможностью повторного использования модели), поэтому я не буду учитывать это в своем ответе.
Я не знаю coffeescript, но я буду использовать Javascript. Ответ действительно технически - передавать модели через параметр options в представление во время создания экземпляра.

Я думаю, что в целом хорошая идея использовать объекты презентатора для управления определенными группами представлений. Этот объект будет создавать экземпляры, которые связаны, и, как вы упомянули, разрешите вводить экземпляр странModel в этот ведущий.
Представьте себе гипотетически, что у вас есть webapp, который отображает карту и список с местами, для которых требуется модель, которую вы описываете по какой-то причине. У вас может быть код, который выглядит так:

var countriesModel = new CountriesModel(); 

var headerPresenter = new HeaderPresenter(); 
var mapPresenter = new MapPresenter(countriesModel); 
var listPresenter = new ListPresenter(countriesModel); 

Что происходит, так это то, что вы создаете экземпляр модели только один раз и вставляете экземпляр в презентаторы, которые этого требуют.
В объекте презентатора вы можете сразу получить доступ к свойствам/методам, установленным в переданной модели.

Этот подход позволяет быстро определить, какие докладчики требуют повторно используемой модели.
Если вам потребуется компонент в новых презентаторах, его легко передать.
Затем в презентаторе вы все равно можете выбрать, какие точки зрения вы хотите отправить модели.

Eg. Ведущий список:

function listPresenter(countriesModel){ 
    this.listView = new ListView({ "model": countriesModel); 
    //More views can be added with the same model instance 
}; 

Внутри представлений или докладчиков вы можете прослушивать события на модели, выполнять ее методы и повторно отображать представления.
Лично я управляю этой логикой от ведущего, потому что это место, где я использую другие внедренные службы и компоненты для выполнения, например. серверные вызовы или конкретные вычисления, которые могут быть общими для разных видов. Обработка этой общей логики для разных представлений легко осуществляется путем передачи агрегатора событий в каждый из экземпляров представления. Представления запускают пользовательские события, чтобы делать то, что требуется, и ведущий прослушивает пользовательские события, выполняет требуемую логику и (повторно) создает представления.
Я предпочитаю сохранять чистоту и сосредоточен на привязке событий DOM/DOM.

Sidenote: Магистральная магистраль предлагает агрегатор событий уровня приложения, который экономит вам боль при передаче в агрегаторах событий для каждого вида отдельно.
Это также очень удобный lib для визуализации представлений от ведущего, используя синтаксис, например:

var someView = new SomeView(); 
var region = new Marionette.Region({ el: "#some-region" }); 
region.show(someView); 

Повторное отображение просмотров с использованием регионов Marionette безопасно для памяти.

Надеюсь, это поможет.

Ответ 2

TBH Я действительно не понимаю, почему вы используете свою модель в качестве deps. Хороший взгляд должен быть абстрагирован от модели, и модель должна быть привязана к виду с маршрута.

// this goes in your view file
var CountryView = Backbone.view.extend({
    // here goes all the view logic to display the model data
    // you can refer to your model using this.model
})

...
// in the router file
var myModel = new CountriesModel();

var router = Backbone.router.extend({
    routes: {
        "": home,
        "home": home
    },
    home: function (){
       var view = new CountryView({ model: myModel});
       view.render(); //if you didn't rendered the view in the initialize method
    }
})

Вы можете получить доступ к другой модели в представлении, прикрепленном к ней во время выполнения в маршрутизаторе

...
// in the router file
var myModel = new CountriesModel();
var anotherModel = new ProjectModel();


var router = Backbone.router.extend({
    routes: {
        "": home,
        "home": home
    },
    home: function (){
       var view = new CountryView({
                               model: myModel
                               anotherModel: anotherModel
                               });
       view.render(); //if you didn't rendered the view in the initialize method
    }
})

а в CountryView прикрепить его к функции инициализации

initialize: function (options){
    this = _.extend(options, this)
    // or
    // this.anotherModel = options.anotherModel
    // this.model = options.model
}

Но вы не смешиваете модели в представлении, просто имеете другое представление для projectModel и используете их как при необходимости

// something like
var countryView = new CountryView({model: myModel});
var projectView = new ProjectView({model: anotherModel});

и сделать их вместе с маршрутизатором

Ответ 3

В вашем представлении вы можете создавать экземпляры, отличные от тех, на которые ссылается this.model. Например:

var SomeView = Backbone.View.extend({

    initialize: function() {
        this.countriesModel = new CountriesModel();

        // Anywhere in your view do stuff with `this.countriesModel`. E.g:
        // this.listenTo(this.countriesModel, ...)
        // this.countriesModel.fetch()
        // etc
    }

});