事件委托给骨干父视图(Delegating events to a parent view in B

2019-07-29 07:23发布

我的看法, TuneBook ,有型的几个子视图ClosedTune 。 我也有各曲调,独立的全网页浏览OpenTune 。 同样的事件中必然ClosedTuneOpenTune ,所以我设计我的应用程序,使他们无论从共享“抽象”视图继承Tune

为了让我的应用程序更可伸缩的,我想事件的每个ClosedTune委托给TuneBook ,但对于维护我想同样的处理程序(存储在那些Tune ),以通过使用TuneBook (虽然他们会显然需要有包裹在一些功能)。

我的问题是,内TuneBook ,找到正确的ClosedTune调用的处理程序。 什么是建筑师一个很好的方式,还是有对事件委托给父视图其他好的解决办法?

-不是重复骨干观的继承与从父扩展事件 (这是关于儿童从父类继承,而我问孩子这是在DOM父的子节点)

Answer 1:

在你的父视图(也从延长Backbone.Events ),我会结合onEvent到DOM事件。 在触发器,它会触发一个事件骨干在内的一些“id”属性,你的孩子知道的意见(大概是一些行标识?)。

var TuneBook = Backbone.View.extend(_.extend({}, Backbone.Events, {
    events: {
        "click .tune .button": "clickHandler"
    },
    clickHandler: function (ev) {
        this.trigger('buttonClick:' + ev.some_id_attr, ev);
    },

}));

那么儿童的意见自然会订阅该关注他们的家长意见活动。 下面我做在initialize传递父视图以及特殊ID属性您在之前使用options

var ClosedTune = Backbone.View.extend({

    initialize: function (options) {
        options.parent.on('buttonClick:' + options.id, this.handler, this);
    },

    handler: function (ev) {
        ...
    },

});

你当然也可以建立类似的用户TuneOpenTune



Answer 2:

这里有几种可能性。

1.集中:商店ClosedTune中的对象TuneBook实例

  1. 店里每一个参考ClosedTunetune_book.tunes 。 你如何填充tune_book.tunes是给你; 既然你提到的加法方法TuneBook ,那就是我如下图所示。

  2. TuneBook事件处理程序,检索ClosedTunetune_book.tunes通过使用类似的id活动对象的属性为关键。 然后调用TuneClosedTune处理程序。

http://jsfiddle.net/p5QMT/1/

var Tune = Backbone.View.extend({
  className: "tune",

  click_handler: function (event) {
    event.preventDefault();
    console.log(this.id + " clicked");
  },

  render: function () {
    this.$el.html(
      '<a href="" class="button">' + this.id + '</a>'
    );

    return this;
  }
});

var ClosedTune = Tune.extend({});

var OpenTune = Tune.extend({
  events: {
    "click .button" : 'click_handler'
  }
});

var TuneBook = Backbone.View.extend({
  events: {
    "click .tune .button" : 'click_handler'
  },

  click_handler: function (event) {
    var tune = this.options.tunes[
      $(event.target).closest(".tune").attr('id')
    ];

    tune.click_handler( event );
  },

  add_tune: function (tune) {
    this.options.tunes[tune.id] = tune;
    this.$el.append(tune.render().el);
  },

  render: function () {
    $("body").append(this.el);
    return this;
  }
});

var tune_book = new TuneBook({
  tunes: {}
});

[1, 2, 3].forEach(function (number) {
  tune_book.add_tune(new ClosedTune({
    id: "closed-tune-" + number
  }));
});

tune_book.render();

var open_tune = new OpenTune({
  id: "open-tune-1"
});

$("body").append(open_tune.render().el);

2.分散:视图对象与使用DOM对象关联jQuery.data()

  1. 当你创建一个ClosedTune ,参考存储它,如this.$el.data('view_object', this)

  2. 在事件侦听器,检索ClosedTune ,如$(event.target).data('view_object')

您可以使用完全相同的处理程序ClosedTune (在TuneBook )和OpenTune ,如果你想要的。

http://jsfiddle.net/jQZNF/1/

var Tune = Backbone.View.extend({
  className: "tune",

  initialize: function (options) {
    this.$el.data('view_object', this);
  },

  click_handler: function (event) {
    event.preventDefault();

    var tune =
      $(event.target).closest(".tune").data('view_object');

    console.log(tune.id + " clicked");
  },

  render: function () {
    this.$el.html(
      '<a href="" class="button">' + this.id + '</a>'
    );

    return this;
  }
});

var ClosedTune = Tune.extend({
  initialize: function (options) {
    this.constructor.__super__.initialize.call(this, options);
  }
});

var OpenTune = Tune.extend({
  events: {
    "click .button" : 'click_handler'
  }
});

var TuneBook = Backbone.View.extend({
  events: {
    "click .tune .button": Tune.prototype.click_handler
  },

  add_tune: function (tune) {
    this.$el.append(tune.render().el);
  },

  render: function () {
    $("body").append(this.el);
    return this;
  }
});

var tune_book = new TuneBook({
  tunes: {}
});

[1, 2, 3].forEach(function (number) {
  tune_book.add_tune(new ClosedTune({
    id: "closed-tune-" + number
  }));
});

tune_book.render();

var open_tune = new OpenTune({
  id: "open-tune-1"
});

$("body").append(open_tune.render().el);

回应发表评论

我认为选择1,而是针对它决定,因为我已经在tunebook调模型的集合,不希望另一个目标我需要保持同步

我想这取决于什么看家样/同步你觉得需要做的,以及为什么。

(例如,在TuneModel.remove()我将需要删除的意见tunebook的列表视图...大概会需要事件要做到这一点,这样的事件唯一的解决方案开始显得更有吸引力)。

为什么你觉得你“需要删除的意见tunebook的列表视图”? (我并不是说你不应该,只是问为什么要。)既然你做什么,你是怎么想@ ggozad的做法在这方面有所不同?

这两种技术存储ClosedTune中的对象TuneBook实例。 在@ ggozad的技术,它只是隐藏的抽象,或许使得你不太明显落后。

在我的例子它们存储在一个纯JS对象( tune_book.tunes )。 在@ ggozad的它们存储在_callbacks通过使用结构Backbone.Events

添加ClosedTune

1。

this.options.tunes[tune.id] = tune;

2。

this.on('buttonClick:' + tune.id, tune.handler, tune);

如果你想摆脱的ClosedTune (说你从文档中删除它tune.remove()和你想要的视图对象完全消失),使用@ ggozad的做法会留下一个孤立的参考ClosedTunetune_book._callbacks除非执行同一种看家的这将使感与我建议的方法:

1。

delete this.options.tunes[tune.id];

tune.remove();

2。

this.off("buttonClick:" + tune.id);

tune.remove();

每个示例的第一行是可选的-这取决于如果你想清理ClosedTune对象与否。

选项2或多或少是我在做什么的权利,但(由于其他原因),我还存放了模型上查看数据属性。$埃尔,我不禁觉得我们有了一个更好的办法不是存储所有的地方引用。

那么,它最终归结到你的偏好如何构建的东西。 如果你喜欢存储更集中的方式查看对象,你可以将它们存储在TuneBook实例,而不是使用jQuery.data 。 见#1:集中。

拉上你存储的引用ClosedTune对象:使用jQuery.data ,或在一个普通的对象TuneBook ,或_callbacksTuneBook

如果你喜欢@ ggozad的做法对你了解,去为它,但它不是魔术的原因。 因为它是这里介绍我不知道应该由抽象的额外水平相比,更简单的版本我目前在#1提供什么优势。 如果有一定的优势,随时填补我进去。



Answer 3:

伟大的解决方案,我已经从其中取出文章 (@戴维-卡德瓦拉德评论)。

扩展一个通用的骨干事件对象并将其存储在一个参考vent

var vent = _.extend({}, Backbone.Events);

它传递给父视图:

var parentView = new ParentView({vent: vent});

子视图将触发一个事件:

ChildView = Backbone.View.extend({    
  initialize: function(options){
    this.vent = options.vent;
  },

  myHandler: function(){
    this.vent.trigger("myEvent", this.model);
  }
});

与父视图是听孩子的事件:

ParentView = Backbone.View.extend({    
    initialize: function(options){
        this.vent = options.vent;
        this.vent.on("myEvent", this.onMyEvent);

        let childView = new ChildView({vent: this.vent});
    },

    onMyEvent: function(){
        console.log("Child event has been ");
    }
});

免责声明-支付该注意vent对象必须被注入到每一个视图,以便您将在本文中更好的设计模式,找到利用。



文章来源: Delegating events to a parent view in Backbone