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

Backbone.js управление состоянием/просмотр инициализации на основе фрагмента URL

Я пытаюсь отслеживать состояние в этом приложении с помощью Backbone.js:

enter image description here

У меня есть "ChartAppModel" с набором значений по умолчанию:

ChartAppModel = Backbone.Model.extend({

defaults: { 
    countries : [], 
    selectedCountries : [],
    year : 1970,
},

initialize: function() { 
    loadAbunchOfData();
    checkStartState();
}

});

Если задан начальный фрагмент, это состояние по умолчанию должно быть перезаписано:

var startState = $.deparam.fragment(); //using Ben Alman BBQ plugin
this.set({selectedCountries: startState.s, year: startState.y});

Теперь, например, SidebarView готов к обновлению:

ChartAppViewSidebar = Backbone.View.extend({

initialize: function(){
      this.model.bind("change:selectedCountries", this.render);
},

render : function(){
      [... render new sidebar with check boxes ...]
},

Проблема в том, что у меня также есть обработчик событий на боковой панели, который обновляет модель:

events: {
"change input[name=country]": "menuChangeHandler",
},

menuChangeHandler : function(){
      [... set selectedCountries on model ...]
},

Итак, будет цикл обратной связи... И тогда мне также понравится способ нажатия нового состояния - так что я слушаю изменения модели:

ChartAppModel = Backbone.Model.extend({

initialize: function() { 
    this.bind("change", this.setState);
}

});

... и относительно скоро этот государственный менеджер рухнет...

Вопросы:

1) Как мне включить мои представления (например, "какие флажки должны быть проверены" ) на основе фрагмента? (любые подсказки о лучших практиках состояния состояния/начала, которые не являются типичным "маршрутом", оцениваются)

2) Как я могу избежать своих представлений, устанавливающих атрибут на модели, которую они сами слушают?

3) Как я могу нажать новое состояние на основе части модели?

Бонус:)

4) Как бы вы описали код для описанного приложения?

Спасибо!

4b9b3361

Ответ 1

Это один четко определенный вопрос!

Возникает вопрос о том, что такое модель. Я считаю, что есть определение, плавающее вокруг того, что составляет модель в мире основы, и я не уверен, что ваша стратегия соответствует этому определению. Также вы сохраняете состояние как в URL-адресе, так и в модели. Вы можете просто сохранить состояние в URL-адресе, как я объясню.

Если бы я делал это, было бы 2 вида. Один для ваших элементов управления приложениями и вложен внутри этого для вашего графика: GraphView и AppView. Модель будет данными, которые вы собираетесь планировать, а не состоянием интерфейса.

Используйте контроллер, чтобы запустить представление приложения, а также обработать любое состояние интерфейса, определенное в URL-адресе.

Возникает вопрос о рычагах состояния в магистрали. Традиционные веб-приложения использовали ссылку /url как основной рычаг состояния, но все, что сейчас меняется. Вот одна из возможных стратегий:

Checkbox Change Event -> Update location fragment -> trigger route in controller -> update the view
Slider Change Event -> Update location fragment -> trigger route in controller -> update the view

Великая вещь в такой стратегии заключается в том, что она заботится о случае, когда URL-адреса передаются или помечены закладкой

Url specified in address bar -> trigger route in controller -> update the view

Я возьму удар по примеру псевдокода. Для этого я сделаю некоторые предположения относительно данных: Данные представляют собой популяцию собак с течением времени (с гранулярностью года), где ползунок должен иметь нижнюю и верхнюю границы, а объемные данные слишком велики, чтобы сразу загрузить его клиенту.

Сначала рассмотрим модель для представления статистических данных. Для каждой точки на графике нам нужно что-то вроде {population: 27000, year: 2003} Позволяет представить это как

DogStatModel extends Backbone.Model ->

и набор этих данных будет

DogStatCollection extends Backbone.Collection ->
    model: DogStatModel
    query: null // query sent to server to limit results
    url: function() {
        return "/dogStats?"+this.query
    }

Теперь посмотрим на контроллер. В этой стратегии, которую я предлагаю, контроллер соответствует своему названию.

AppController extends Backbone.Controller ->
    dogStatCollection: null,
    appView: null,

    routes: {
         "/:query" : "showChart"
    },

    chart: function(query){
        // 2dani, you described a nice way in your question
        // but will be more complicated if selections are not mutually exclusive
        // countries you could have as countries=sweden;france&fullscreen=true
        queryMap = parse(query) //  
        if (!this.dogStatCollection) dogStatCollection = new DogStatCollection
        dogStatCollection.query = queryMap.serverQuery
        if (!this.appView) {
           appView = new AppView()
           appView.collection = dogStatCollection
        }
        appView.fullScreen = queryMap.fullScreen
        dogStatCollection.fetch(success:function(){
          appView.render()
        })            
    }

Ответ 2

2) Как я могу избежать своих представлений, устанавливающих атрибут на модели, которую они сами слушают?

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

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

3) Как я могу нажать новое состояние на основе части модели?

// for each attribute
_.each(["attribute1", "attribute2", "attribute3", ...], _.bind(function(val) {
    // bind the change
    // bind the setState with `this` and the `value` as the first parameter
    this.bind("change:" + value, _.bind(this.setState, this, value));
}, this));