【问题标题】:How to avoid a large number of dependencies in AngularjsAngularjs中如何避免大量依赖
【发布时间】:2014-04-30 07:27:39
【问题描述】:

我有一个 Angular 应用程序。它运行良好,但随着我的应用程序变得越来越大,我担心我必须在每个控制器中注入大量依赖项。

例如

app.controller('viewapps',[
    '$scope','Appfactory','Menu','$timeout','filterFilter','Notice', '$routeParams', 
    function($scope,Appfactory,Menu,$timeout,filterFilter,Notice,$routeParams) {
        //controller code..    
}])

我确信依赖项列表将来会增加。我在这里做错了吗?这是正确的方法吗?有效处理此问题的最佳方法是什么?

【问题讨论】:

    标签: angularjs dependency-injection


    【解决方案1】:

    尝试将尽可能多的逻辑转移到服务中,甚至只是让控制器方法充当“路由-传递”方法。一段时间后,如果您想在其他控制器/指令中使用类似的方法,您会发现它非常有用。无论如何,我认为7次注射并不多:)

    (编辑:见下方 Matt Way 的评论) 另外,提示 - 在较新版本的 Angular 中,您不必编写此数组,只需:

    app.controller('viewapps', function($scope,Appfactory,Menu, $timeout,filterFilter,Notice,$routeParams){
       //controller code..    
    }])
    

    【讨论】:

    • 您从来不需要这样做,但是使用数组是为了让您可以安全地缩小您的角度代码之类的事情。最佳做法是始终使用数组标签。
    • IMO 数组符号最好留给可以插入它的构建步骤。对我来说,最好的做法是不要重复自己,把这个负担留给机器。见 github.com/btford/ngmin
    【解决方案2】:

    如果没有确切的用例,或者在控制器中查看确切的代码,很难具体说明,但看​​起来你的控制器可能做的太多了(或者在你以后添加东西时可能最终做的太多了)。你可以做 3 件事:

    • 将更多逻辑委托给注入的服务。

    • 分成不同的控制器,所以每个控制器只有(大约)一项职责。

    • 将输出分成指令,每个指令都有自己的控制器和模板,并允许通过属性和指令的scope 选项传入和输出选项。这通常是我的首选,因为您最终会构建一套可重用的组件,每个组件都有一个迷你 API。

      至少在我看来,这样使用指令很好。它们不仅仅用于处理原始 Javascript 事件或直接访问 DOM。

    【讨论】:

    • 我为每个数据库表都有一个工厂。在一个控制器中,我需要查询 6 个表,我必须注入 6 个工厂+$location+$scope。这有点太多了。现在我把它分成不同的控制器来获取特定的数据。我想这是最好的方法......我认为你的第 2 点是应该做的。
    • 我不认为这是解决问题的方法,而是另一种选择。
    【解决方案3】:

    我一直在玩基于控制器捆绑服务的想法。

    所以在你的例子中你会重构你的; AppFactory、Menu、filterFilter 和 Notice 服务合并为一个服务,例如ViewAppsServices。

    然后您将使用 ViewAppsServices.AppFactory.yourFunction() 等服务。

    在我看来,这样你至少可以将你的注入转移到另一个文件中,清理你的控制器。

    我认为可读性会受到一些影响,因为其他开发人员将不得不查看捆绑包而不是控制器本身。

    这是我整理的JSFiddle 来演示它的工作原理;这就是我想象的你的工作方式。

    .service('ViewAppsServices', ['AppFactory', 'Menu', 'filterFilter', 'Notice', 
    function (AppFactory, Menu, filterFilter, Notice) {
        return {
            AppFactory: AppFactory,
            Menu: Menu,
            filterFilter: filterFilter,
            Notice: Notice
        };
    } ])
    

    【讨论】:

    • 我想这会让我的控制器很重......因为有时我不需要所有的东西。
    【解决方案4】:

    我的方法是使用$injector,当有很多依赖时:

    app.controller('viewapps', ['$scope','$injector',function($scope,$injector){                               
        var Appfactory = $injector.get('Appfactory');
        var Menu = $injector.get('Menu'); 
        //etc...
    }]);
    

    优点:

    • 可以安全地缩小和混淆代码
    • 当你将依赖声明为函数的参数时,你不需要计算依赖的索引

    【讨论】:

    • 有一些工具,比如github.com/btford/ngmin,可以预先缩小 Angular,所以你仍然可以用“好的”方式编写函数,并最终缩小代码。此外,这是否可以从本质上掩盖通常建议避免使用的长参数列表? stackoverflow.com/a/175035/1319998
    • -1 的方法 :) 它击败了 DI 的主要优点之一。每个资源都应该明确说明其依赖关系。使用$injector 会混淆资源的实际依赖关系(在本例中为controller)并破坏可维护性。 (当心那个最终会维护你的代码和知道你住的地方的精神变态者。他一点也不开心......)
    • 给定的 $injector 解决方案是服务定位器模式的实现。 This is an anti-pattern(在 Javascript 中也是如此)应该避免使用。此外,您现在隐藏了真正的原因,即 Single Responsibility Principle 违规。
    • @Steven 您关于反模式的链接不适用于 Javascript。无论如何,浏览器通过 runtime* 解释 Javascript(没有 *compile-time 的东西),它并不意味着您将服务作为函数的参数或使用$injector 注入。几乎一样。我假设您不熟悉 Javascript,尤其是 AngularJS。我也知道单一责任原则,但我不知道你为什么在这里提到它。您的评论非常笼统,超出了问题的背景。
    • @Engineer 我可以明白为什么 SRP 上的要点会在上下文中:OP 建议的长参数列表会变得更长,这表明控制器将与所有注入的依赖项进行交互.这反过来表明控制器有许多责任。
    猜你喜欢
    • 2014-12-08
    • 2020-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-06
    • 1970-01-01
    • 2011-03-20
    相关资源
    最近更新 更多