最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Multiple view on same page with backbone.js - Stack Overflow

programmeradmin1浏览0评论

I am testing backbone by making a craft system. You have elements (stone, wood, gold..) and you make items with it.

To make items, you have some recipe, so I have two models:

Recipe 
Element

At the bottom of my page, I make a list of my elements using a backbone view. It work very well. When you click on an element, I add it to my bag.

My root router :

class MyTest.Routers.App extends Backbone.Router
   routes:
    '': 'index'
    'elements/:id' : 'show'

   initialize: ->
     @elements = new MyTest.Collections.Elements()
     @elements.fetch()

   index: ->
      view = new MyTest.Views.ElementsIndex(collection: @elements)
      $('#elements').html(view.render().el)
      @initRecipe()

   initRecipe: ->
     @recipes = new MyTest.Collections.Recipes()
     @recipes.fetch()
     view = new MyTest.Views.RecipesIndex(collection: @recipes)
     $('#recipes').html(view.render().el)

   show: (id) ->
      alert "Element #{id}"

My element view :

class MyTest.Views.Element extends Backbone.View

  template: JST['elements/element']

  events:
    'element_rended': 'initImagesDatas'
    'click  img' : 'observeImageEvents'
    'click .more': 'addToBag'
    'click .less': 'decreaseNumber'

  tagName : 'li'

  render: ->
    $(@el).html(@template(element: @model))
    @currentImage = $(@el).find('img')
    @craftBox = null
    $(@el).trigger('element_rended')
    this

  initImagesDatas: ->
    @currentImage.data('alreadyAdded',false)
    @currentImage.data('position',false)

  observeImageEvents: (event) ->
    event.preventDefault()
    $(event.target).parent().next('div.element-description').fadeToggle()

  isAdded: ->
    if (@currentImage.data('alreadyAdded') == true) then true else false

  addToBag: (event) ->
    if (@isAdded())
      @incrementNumber()
    else
      @getNextCraftBox().append(@currentImage.clone())
      @currentImage.data('alreadyAdded',true)
      @incrementNumber()

  getNextCraftBox: ->
    returnItem = $('#craft-area li').eq(0)
    $('#craft-area li').each ->
      if $(this).find('img').length == 0
        returnItem = $(this)
        return false
    @craftBox = returnItem
    return returnItem

  incrementNumber: ->
    @craftBox.find('.number').show()
    @craftBox.find('.number').text(parseInt(@craftBox.find('.number').text())+ 1)

  decreaseNumber: ->
    if parseInt(@craftBox.find('.number').text()) == 1
      @removeToBag()
    else
      @craftBox.find('.number').text(parseInt(@craftBox.find('.number').text())- 1)

  removeToBag: ->
    if (@isAdded())
      @craftBox.parents('ul').append('<li><div class="number">0</div></li>')
      @craftBox.remove()
      @currentImage.data('alreadyAdded',false)

My recipe view :

class MyTest.Views.Recipe extends Backbone.View

  recipeSelected: null

  template: JST['recipes/recipe']

  tagName : 'li'
  className: 'recipe-li',

  events:
      'click': 'preFillItemsRequired'

  preFillItemsRequired: ->
    if $(@el).hasClass('selected') then $(@el).removeClass('selected') else $(@el).addClass('selected');
    recipeSelected = @model;
    @addIngredient()

  addIngredient: ->
    console.log('pass')

  render: ->
    $(@el).html(@template(recipe: @model))
    this

My question is how can I interact between my two views? How can I get my selected recipe (without using css selector) from my element's view for example?

My test looks like:

I am testing backbone by making a craft system. You have elements (stone, wood, gold..) and you make items with it.

To make items, you have some recipe, so I have two models:

Recipe 
Element

At the bottom of my page, I make a list of my elements using a backbone view. It work very well. When you click on an element, I add it to my bag.

My root router :

class MyTest.Routers.App extends Backbone.Router
   routes:
    '': 'index'
    'elements/:id' : 'show'

   initialize: ->
     @elements = new MyTest.Collections.Elements()
     @elements.fetch()

   index: ->
      view = new MyTest.Views.ElementsIndex(collection: @elements)
      $('#elements').html(view.render().el)
      @initRecipe()

   initRecipe: ->
     @recipes = new MyTest.Collections.Recipes()
     @recipes.fetch()
     view = new MyTest.Views.RecipesIndex(collection: @recipes)
     $('#recipes').html(view.render().el)

   show: (id) ->
      alert "Element #{id}"

My element view :

class MyTest.Views.Element extends Backbone.View

  template: JST['elements/element']

  events:
    'element_rended': 'initImagesDatas'
    'click  img' : 'observeImageEvents'
    'click .more': 'addToBag'
    'click .less': 'decreaseNumber'

  tagName : 'li'

  render: ->
    $(@el).html(@template(element: @model))
    @currentImage = $(@el).find('img')
    @craftBox = null
    $(@el).trigger('element_rended')
    this

  initImagesDatas: ->
    @currentImage.data('alreadyAdded',false)
    @currentImage.data('position',false)

  observeImageEvents: (event) ->
    event.preventDefault()
    $(event.target).parent().next('div.element-description').fadeToggle()

  isAdded: ->
    if (@currentImage.data('alreadyAdded') == true) then true else false

  addToBag: (event) ->
    if (@isAdded())
      @incrementNumber()
    else
      @getNextCraftBox().append(@currentImage.clone())
      @currentImage.data('alreadyAdded',true)
      @incrementNumber()

  getNextCraftBox: ->
    returnItem = $('#craft-area li').eq(0)
    $('#craft-area li').each ->
      if $(this).find('img').length == 0
        returnItem = $(this)
        return false
    @craftBox = returnItem
    return returnItem

  incrementNumber: ->
    @craftBox.find('.number').show()
    @craftBox.find('.number').text(parseInt(@craftBox.find('.number').text())+ 1)

  decreaseNumber: ->
    if parseInt(@craftBox.find('.number').text()) == 1
      @removeToBag()
    else
      @craftBox.find('.number').text(parseInt(@craftBox.find('.number').text())- 1)

  removeToBag: ->
    if (@isAdded())
      @craftBox.parents('ul').append('<li><div class="number">0</div></li>')
      @craftBox.remove()
      @currentImage.data('alreadyAdded',false)

My recipe view :

class MyTest.Views.Recipe extends Backbone.View

  recipeSelected: null

  template: JST['recipes/recipe']

  tagName : 'li'
  className: 'recipe-li',

  events:
      'click': 'preFillItemsRequired'

  preFillItemsRequired: ->
    if $(@el).hasClass('selected') then $(@el).removeClass('selected') else $(@el).addClass('selected');
    recipeSelected = @model;
    @addIngredient()

  addIngredient: ->
    console.log('pass')

  render: ->
    $(@el).html(@template(recipe: @model))
    this

My question is how can I interact between my two views? How can I get my selected recipe (without using css selector) from my element's view for example?

My test looks like:

Share Improve this question edited Apr 10, 2013 at 19:05 thegreyspot 4,1095 gold badges30 silver badges34 bronze badges asked Mar 1, 2012 at 13:39 SebastienSebastien 6,66014 gold badges59 silver badges105 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 3

The easiest and the propert MVC way to do it is having them to observe the same model.

A view should not be able to interact with another view, but it should be able to observe a model and change the model state, or change its own state based on the model state.

var MyTest.Views.Recipe = Backbone.View.extend({
    initialize: function(){
        this.model.on('change:selected', this.render, this);
    },
    events: {
        'click': function(){
            this.model.set('selected', this.cid);
        }
    },
    render: function(){
        if( this.model.get('selected') == this.cid ) {
            this.$el.addClass('selected')
        }
        else {
            this.$el.removeClass('selected')
        }
    }
});

var model = new Backbone.Model();

var view1 = new MyTest.Views.Recipe({
    model: model,
});

var view2 = new MyTest.Views.Recipe({
    model: model,
})

// ...

I think the easiest way is to use the event triggers

http://lostechies./derickbailey/2011/08/30/dont-limit-your-backbone-apps-to-backbone-constructs/

shows the thought at the bottom

or the simpler usage pattern

https://github./derickbailey/backbone.marionette and look at app.vent: Event Aggregator

发布评论

评论列表(0)

  1. 暂无评论