木偶 - 多次触发事件

时间:2015-07-23 12:30:38

标签: javascript backbone.js marionette

我在处理视图和集合之间的事件时遇到了麻烦。在下面的示例中,您可以找到我的webapp的简短版本以及现在如何处理事件。

这里发生的事情是,当从 menu1 切换到 menu2 或甚至倒退时,会导致“APP:change_city”事件侦听器堆叠起来。因此,当我然后触发此事件时,它会在我在菜单之间切换时多次调用方法OnCityChange()

我现在还不确定我是否正确使用了事件聚合器(eMgr)。 有人可以帮忙吗?

eMgr.js

define(['backbone.wreqr'],function(Wreqr){
    "use strict";
    return new Wreqr.EventAggregator();
})

AppRouter.js

define(['marionette'],  function (Marionette) {
    "use strict";

    var AppRouter = Marionette.AppRouter.extend({
        appRoutes: {
            'menu1' : 'showMenu1',
            'menu1' : 'showMenu2'
        }
    });

    return AppRouter;
});

AppControler.js

define(['underscore', 'backbone', 'marionette', '../eMgr'],  function (_, Backbone, Marionette, eMgr) {
    "use strict";

    var Controller = Marionette.Controller.extend({
            initialize: function(){
                console.log("AppRouter - Init")
            },

            showMenu1: function (city) {
                console.log(" [Info] [AppControler] opening Menu1");
                eMgr.trigger("APP:open_menu", { menu: "Menu1", city: city});
            },

            showMenu2: function (city) {
                console.log(" [Info] [AppControler] opening Menu2");
                eMgr.trigger("APP:open_menu", { menu: "Menu2", city: city});
            }
    });

    return Controller;
});

App.js

define([ 'backbone', 'underscore', 'marionette', 'eMgr',  
    'layouts/MainMenu/layoutview.menu1',
    'layouts/MainMenu/layoutview.menu2',
    'controllers/AppController', 'routers/AppRouter'], 
    function (Backbone, _, Marionette,  eMgr,  
    lv_mainmenu1, lv_mainmenu2,
    AppController, AppRouter) {
    "use strict";

    var MyApp = new Marionette.Application();
    var controller = new AppController();

    MyApp.addRegions({
        .....
        mainmenu: '#main_menu',
        .....
    });

    MyApp.listenTo(eMgr, "menu_changed",function(eData){
        switch(eData.menu){
            case "Menu1":
                MyApp.mainmenu.show(new lv_mainmenu1(eData));
                break;
            case "Menu2": 
                MyApp.mainmenu.show(new lv_mainmenu2(eData));
                break;
        }
    });

    MyApp.addInitializer(function(options) {
        var router = new AppRouter({
          controller : controller
        });
    });


    MyApp.on("start", function(){
      if (Backbone.history){
          Backbone.history.start();
      }
    });

    $(document).ready(function() {
        MyApp.start();
    });
});

layoutview.menu1.js

define([ 'backbone', 'underscore', 'marionette', 
            'templates/template.mainmenu', 
            'layouts/MainMenu/collectionview.categories'],
    function (Backbone, _, Marionette, t_Menus, c_Categories, cv_Categories) {
    "use strict";
    var Menu1LayoutView = Marionette.LayoutView.extend({

        template: t_Menus['menu1'],

        regions: {
            menu : '#menu'
        },

        initialize: function(options){
            this.city = options.city
        },


        onRender: function(){
        },

        onShow: function(){
            this.menu.show(new cv_Categories({city:this.city}));
        }
    });

    return Menu1LayoutView;
});

collectionview.categories.js

define([ 'backbone', 'underscore', 'marionette',
    'layouts/MainMenu/compositeview.subcategories',
    'collections/MainMenu/MM.collection.categories'], 
    function (Backbone, _, Marionette, cv_Subcategories, c_Categories) {
    "use strict";
    var CategoriesCollectionView = Marionette.CollectionView.extend({

        initialize: function(options){
            this.collection = new c_Categories([], {city: options.city});
        },

        getChildView: function(model){
            return cv_Subcategories;
        },

        onRender: function(){
        },
         onShow: function(){
        }
    });

    return CategoriesCollectionView;
});

这是获取所有类别数据的地方,它还会在触发APP:change_city事件后重新获取数据。

MM.collection.categories.js

    define([ 'underscore',  'backbone', 'eMgr','models/MainMenu/MM.model.category'], function(_, Backbone, eMgr, m_Category){
  var CategoriesCollection = Backbone.Collection.extend({
    model: m_Category,

    initialize: function(attr, opts) {
        this.city = opts.city;
        this.fetch();
        eMgr.once("APP:change_city", this.OnCityChange, this)
    },

    url: function(){
        return 'AF_GetCategories?city='+this.city;
    },

    OnCityChange: function(eData){
        /// this is the part which is being called multiple times !!!!!   ////
        /// when checking eMgr's events , it shows that the events are stacking up .. 
        this.url= 'AF_GetCategories?city='+eData.city;
        this.fetch();
    }
  });

  return CategoriesCollection;
});

compositeview.subcategories.js

define([ 'backbone', 'underscore', 'marionette',
    'templates/template.mainmenu', 
    'layouts/MainMenu/itemview.subcategory'], 
    function (Backbone, _, Marionette, t_MainMenu, iv_Subcategory) {
    "use strict";
    var SubcategoriesCompositeView = Marionette.CompositeView.extend({

        template: t_Menus['subcategorieslayout'],

        childViewContainer: "#category-wrapper",

        getChildView: function(model){
            return iv_Subcategory;
        },

        initialize: function(){
            this.collection = this.model.get("subcategories");
        },


        onRender: function(){
        },

        onShow: function(){
            this.$el.find("#loading").fadeOut(150);
        }
    });

    return SubcategoriesCompositeView;
});

1 个答案:

答案 0 :(得分:0)

我得出结论,将事件监听器this.listenTo("custom_event", this.do_something)保留在模型或集合中并不是一个好主意。在 menu1 menu2 之间切换时,事件未正确清理。它只在我加载任何视图之前手动调用eMgr.stopListening()时才有效。

所以我尝试将所有事件监听器从models/collections移动到他们的视图和Voila!...一切正常!事件不再像以前那样被多次触发。

相关问题