设计Backbone.js应用程序的依赖注入系统的范围问题

时间:2013-11-22 21:42:48

标签: javascript backbone.js dependency-injection scope

我们的商店刚刚采用了Backbone,甚至还给了我试用木偶的绿灯。然而,后者并没有给我带来的好处(可能是由于我的无知),所以我试图设计一个轻量级的依赖注入系统,我的所有Backbone视图都获得了一个“应用程序”的实例“我自己设计的对象。

我的系统基于a (necro) answer I posted yesterday,以下是适合我的代码。但是,我不希望在injectViewsWithApp函数内为每个视图都有重复的代码块,而是希望循环遍历视图。但这是我无法弄清楚如何在循环内部工作的地方,我认为这是某种范围问题。

我将继续努力,以便在周末开始前的剩余时间内发布代码更新。

define(['backbone', './app/views/searchform', './app/views/searchresults', './app/views/FooBardetailrow'],

    function(Backbone, SearchFormView, SearchResultsView, FooBarDetailRowView) {
        var APP = initApp();
        injectViewsWithApp();
        launchApp();

        function initApp() {
            return {
                collections : { // No need for separate files/modules if each view gets injected with the APP
                    extendedHaulFooBars : new (Backbone.Collection.extend({})),
                    stn333sts : new (Backbone.Collection.extend({})), 
                    FooBarTypes : new (Backbone.Collection.extend({})),
                    FooBarSymbols : new (Backbone.Collection.extend({})),
                    FooBarSearchParams : new (Backbone.Collection.extend({}))               
                },
                defaultModel : Backbone.Model.extend({}),
                views : {}
            };      
        }

        function injectViewsWithApp() {
            SearchFormView.instantiator = SearchFormView.extend({
                initialize : function() {
                    this.app = APP;
                    SearchFormView.prototype.initialize.apply(this, arguments);
                }
            });

            SearchResultsView.instantiator = SearchResultsView.extend({
                initialize : function() {
                    this.app = APP;
                    SearchResultsView.prototype.initialize.apply(this, arguments);
                }
            });

            FooBarDetailRowView.instantiator = FooBarDetailRowView.extend({
                initialize : function() {
                    this.app = APP;
                    FooBarDetailRowView.prototype.initialize.apply(this, arguments);
                }
            });
        }    

2 个答案:

答案 0 :(得分:1)

我简化了一些事情并获得了以下“工作”。但是,我想将view.instantiator分配回视图,这我无法开始工作:(如果他们可以做到这一点,肯定会接受别人的答案,最后我可以简单地调用“new MyView()”并且可以访问APP / app - 否则我认为以下情况并不是那么糟糕。

var APP = {foo : 'bar'};
var MyView = Backbone.View.extend({});
var views = [MyView];

for (var i=views.length; i--; ) {
    var view = views[i];

    view.instantiator = view.extend({
        initialize : function() {
            this.app = APP;
            view.prototype.initialize.apply(this, arguments);
        }
    });

    console.log(new view.instantiator().app.foo);
}
console.log(new MyView.instantiator().app.foo);

// OUTPUT:'bar'乘以2

答案 1 :(得分:0)

这是另一个可以说是更好的方式;正如所展示的那样,继承甚至是可能的,这在我的案例中尤其重要。感谢this fine answer如何保留' app'跨调用ParentView和ChildView模块。

define(['backbone'],

    function(Backbone) {
        var APP = {
            foo : 'bar'
        };

        var MyParentView = (function() {
            var app;

            return function() {
                return {
                    ctor : Backbone.View.extend({
                        initialize : function() {
                            this.app = app;
                        }
                    }),

                    inject : function(_app) {app = _app;}
                }
            }
        })();

        var MyChildView = (function() {
            var app;

            return function() {
                return {
                    ctor : MyParentView().ctor.extend({
                        initialize : function() {
                            console.log(this.app); // OUTPUT: undefined
                            MyParentView().ctor.prototype.initialize.apply(this, arguments);
                            console.log(this.app.foo); // OUTPUT: bar
                        }
                    }),

                    inject : function(_app) {app = _app;}
                }
            }
        })();           

        var injectableViews = [MyParentView, MyChildView];

        for (var i = injectableViews.length; i--; ) {
            injectableViews[i]().inject(APP);   
        }

        new (MyChildView().ctor)();
    }
);