search

Home  >  Q&A  >  body text

javascript - Backbone里两个view(或者说collection)怎么交互?

我有viewA、viewB,分别对应collectionA、collectionB(他们model类型相同)
目标:点击viewA中一个元素时,将这个元素对应的model添加到collectionB,viewB同上所述
我该怎么做?

var ViewA = Backbone.ViewA.extend({
  el: $('xxx'),
  .....
  events: {
   "click": "trans"
  },
  trans: function(event) {
    var index = event.target.dataset.n;//通过data、元素index之类乱七八糟的获取序列号,总之不重要
    //我疑惑的是下面的
    var model = this.collection.at(index);
    collectionB.add(model) //这样也太傻了吧
  }
});
var viewA = new ViewA({collection: collectionA})

感觉别别扭扭,依赖乱七八糟的

巴扎黑巴扎黑2902 days ago429

reply all(5)I'll reply

  • 迷茫

    迷茫2017-04-10 14:26:30

    楼主的意思比较清楚,而且感觉是对的,乱乱的,其实是因为这样写会太耦合,ViewA不应该包含ViewB

    而最好通过事件进行交互。

    如:

    var eventAcrossView = _.extend({}, Backbone.Events);
    
    // view one needs to trigger an event in view2
    ViewA = Backbone.View.extend({
    
        trans: function(event) {
            eventAcrossView.trigger('viewAClicked', { 'some' : 'data' } );
        })
    })
    
    ViewB = Backbone.View.extend({
        initialize: function() {
            eventAcrossView.on('viewAClicked', this.onViewAClicked, this);
        },
        onViewAClicked : function() {
            // update model
        }
    })
    

    reply
    0
  • 高洛峰

    高洛峰2017-04-10 14:26:30

    var ViewA = Backbone.View.extend({
      el: $('xxx'),
      events: {
       "click": "trans"
      },
      trans: function(event) {
        var index = event.target.dataset.n;
        var model = this.collection.at(index);
        this.trigger('trans', model)
      }
    });
    
    var ViewB = Backbone.View.extend({
      receive: function (model) {
        this.collection.add(model)
      }
    });
    
    var viewA = new ViewA({collection: collectionA})
    var viewB = new ViewB({collection: collectionB})
    
    // 这样
    viewA.on('trans', function (model) {
      viewB.receive(model)
    })
    
    // 或者
    viewB.listenTo(viewA, 'trans', function (model) {
      this.receive(model)
    })
    

    如果没有弄懂Backbone,不建议碰Marionette,因为用不好它。

    reply
    0
  • 天蓬老师

    天蓬老师2017-04-10 14:26:30

    View 是用来做什么的?它是用来 render 内容的,所以对数据本身的操作详细过程怎么可以封装到 View 里面?你可以在 View 里面对 Model 进行操作,但是操作本身请定义在 Model 或者 Collection 内。
    此外,Backbone 直写复杂页面交互逻辑时确实不太好组织代码,所以我推荐你使用 Marionette + Backbone,像现在这种情况的话,在 Marionette 内可以使用 CollectionView 来处理 Collection,而使用 ItemView 来处理单个 Model 的情形。

    reply
    0
  • PHPz

    PHPz2017-04-10 14:26:30

    楼主的代码,我觉得写的没问题。不知楼主究竟是哪里不满意,想写成什么样子?

    reply
    0
  • ringa_lee

    ringa_lee2017-04-10 14:26:30

    我觉得这完全看复用,如果viewA viewB都不会在别的地方复用,那怎么耦合都无所谓,没必要故意拆

    如果其中某一个view会被复用,那么想想怎么被复用就知道怎么解耦了

    顺便说一下以我揣测的这个系统的其余部分,我的做法可能是把A和B抽一个共同部分ListView出来,列表视图能够输出列表项被点击的事件,然后为题主这个情形写个新的叫ABListView之类的玩意儿

        #new ABListView({A: CollectionA, B: CollectionB})
    
        ABListView = View.extend
            initialize: (option)->
                this.children = [option.A, option.B].map (collection, k)->
                    child = new ListView {collection: collection}
                    child.on 'itemClick', this.childItemClick
                    child
    
            childItemClick: (event)->
                #假设event已经有我们要的"本次点击对应view"和“本次点击对应model”
                #1-k 就是 1<==>0 互换
                this.children[1 - this.children.indexOf event.view].collection.add event.model
    
    

    reply
    0
  • Cancelreply