【问题标题】:DelegateEvents: Child itemViews's not removed on deletion of model from collectionDelegateEvents:从集合中删除模型时未删除子 itemViews
【发布时间】:2023-03-06 10:27:01
【问题描述】:

我有一个collectionview ItineraryEditorView,它被换入和换出布局区域。 collectionView 的同一个实例使用region.show 交换,而不是每次都为collectioView 创建新实例。集合上的渲染方法调用delegateEvents() 方法。

    ItineraryEditorView = Marionette.CollectionView.extend({
    tagName: "div",
    emptyView: EmptyItineraryDayView,
    itemView: ItineraryDayView,
    initialize: function (options) {            
    },  
    render: function() {
        Marionette.CollectionView.prototype.render.apply(this);
        this.delegateEvents();
    },
});

视图被关闭区域换出:

plannerLayout.itineraryEditorRegion.close();

在视图中交换:

itineraryEditorView.delegateEvents();
plannerLayout.itineraryEditorRegion.show(itineraryEditorView);

通过监听从itemViewcollectionView 的冒泡事件来删除模型(有效,这里没有问题)

itineraryEditorView.on("itemview:delete:day", function(childView, model)    {
    days.remove(model); //days coll is passed in to coll view on instance creation
    holiday.save();
});

我希望这足以确保在从基础天数集合中移除模型时移除/关闭集合视图中的子 itemViews。我可以看到集合实际上被修改并保存在服务器上,但是集合视图没有改变。 这种情况当然适用于第一次换出集合视图之前。 科尔。在我重新访问另一个选项卡并返回此选项卡后,视图确实会自行更新(因此呈现整个集合 - 确认更改/删除)

解决此问题的最佳方法是什么?如果我重新创建集合视图的实例,它确实会导致代码中丢失其他“打开”句柄。

【问题讨论】:

  • 您手动调用 delegateEvents 的事实让我感到怀疑。关闭区域后是否重用视图?
  • @chris 是的,我正在重用视图。
  • Marionette 的设计初衷不是重复使用封闭视图。该主题可能对您有所帮助:stackoverflow.com/questions/17920499/…

标签: backbone.js marionette backbone-views backbone-events


【解决方案1】:

无需手动调用delegateEvents - Backbone 在视图的构造函数中执行此操作。当您关闭该区域时,该区域将关闭您的视图,删除所有内部引用并解除绑定所有事件,为垃圾收集做准备。一旦一个视图被close()'d,它不应该被再次使用。解决您的问题的方法应该是 new 将您的 ItineraryEditorView 的另一个实例传递给 show 上的区域。

另外,在调用region.show(view) 之前不必调用region.close()show 做的第一件事是close() 当前视图,如果有的话。我建议修改您的代码如下:

ItineraryEditorView = Marionette.CollectionView.extend({
    // tagName: "div", // <-- unnecessary as written - default tag

    emptyView: EmptyItineraryDayView,

    itemView: ItineraryDayView

    // this empty override is unnecessary as written - recommend removing it
    // initialize: function (options) {           
    // },

    // this override is unnecessary as written - remove it:
    // render: function() {
    //     Marionette.CollectionView.prototype.render.apply(this);
    //     this.delegateEvents();
    // },
});

...

// plannerLayout.itineraryEditorRegion.close(); <-- delete this line; it's not needed
// itineraryEditorView.delegateEvents();        <-- ditto

由原始帖子编辑

// define a delegate to handle events shared across multiple instances of the view:
function handleDeleteChild(childView, model) {
    days.remove(model); //days coll is passed in to coll view on instance creation
    holiday.save();
});

// create the ItineraryEditorView
// NOTE: As written this will likely conflict with your current code;
//       update as required
var itineraryEditorView = new ItineraryEditorView(options);

// bind event listeners to it
itineraryEditorView.on("itemview:delete:day", handleDeleteChild);

// show it
plannerLayout.itineraryEditorRegion.show(itineraryEditorView);

【讨论】:

  • 感谢您的回复。但是,如果我使用新的视图实例,其他应用程序事件即。 view.on("myevent") 停止工作。我无法理解相同的原因,但我猜这是一个单独的问题?唯一的解决方法是不在视图中使用 this.trigger,而是传入一个布局实例来查看并使用 layout.trigger!?
  • 我已通过删除委托事件尝试了上述代码,但事件未按预期工作。在我明确调用 delegateEvents 后它们确实起作用了。
  • 如果您在设计应用时认为可以重用关闭的视图,那么这些症状是有道理的。关闭操作应该被视为 Marionette 视图的析构函数(想想 C# 或 Java)。关闭视图后,您对其所做的任何外部引用都需要删除,并且任何事件侦听器都需要解除绑定。由于您要创建一个新视图来代替它,因此您需要重新绑定以前附加到旧视图的所有事件侦听器。
  • 我已修改代码以显示如何重新绑定您问题中定义的delete 事件;可能需要在您应用的其他地方进行类似的更改。
  • 您修改的代码是一个不错的选择(短期内)。谢谢你分享这个。但是,这确实意味着,为了将来验证应用程序,最好现在花时间重写一些代码并只使用新视图,而不管下一版本的 marrionette 是否允许重用视图。
猜你喜欢
  • 2013-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-07
  • 2011-08-11
  • 1970-01-01
  • 2017-01-02
相关资源
最近更新 更多