Магистраль: использование данных модели и функций в представлении
Я новичок в 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
}
});