AngularJS严格依赖注入模式有什么好处?

23

最近我了解到AngularJS的Strict DI模式。使用它有什么目的和好处?在移动设备上使用它是否能够显著提高性能?

我尝试将其应用于我的代码,并且在编写代码时没有进行任何注释。但是,在构建时进行了代码压缩和ng-annotate操作。但是,为什么在我将Strict DI模式添加到我的代码后,仍然会出现错误提示"需要显式注释"?


2
我相信非严格依赖注入代码的主要好处之一是无法进行缩小,因为它依赖于在运行时检查变量名称。 - CollinD
你正在使用哪些构建工具? - Olavi Sau
@OlaviSau 我正在使用 gulp-ng-annotate 和 gulp-uglify 作为我的构建工具。 - user1995781
@user1995781 我更新了答案,基本上gulp是一个流,所以它可以同时处理数据,这意味着如果你同时运行uglify和annotate,uglify可能会先运行,从而破坏一些东西。 - Olavi Sau
1
@OlaviSau 感谢您的回答。我认为这些东西不会出错,因为当我不处于严格的 DI 模式时,我的代码执行没有任何错误。 - user1995781
@user1995781 我认为ng-annotate在某些特殊情况下无法正常工作(他们在自己的readme中谈到了可靠性)。在抛出错误的位置之前添加/@ngInject/。https://github.com/olov/ng-annotate#explicit-annotations-with-nginject - Olavi Sau
4个回答

40

Strict DI Mode通常会在运行时发现不符合代码最小化的规范时抛出错误,但请注意,代码可能是正确的,没有逻辑或语法错误。

引用文档:

  

如果应用程序元素上存在此属性,则注入器将以“strict-di”模式创建。这意味着应用程序将无法调用不使用显式函数注释(因此不适合最小化)的函数,如依赖注入指南中所述,并且有用的调试信息将有助于跟踪这些错误的根源。

例如,以下代码触发错误,因为($scope, $http, $filter)没有使用$inject进行显式注入,也没有给.controller(A,B)方法提供一个数组作为第二个字段。

angular.module("myApp", [])
// BadController cannot be invoked, because
// the dependencies to be injected are not
// explicitly listed.
.controller("BadController", function($scope, $http, $filter) {
  // ...
});

正确的片段:

angular.module("myApp", [])
  .controller("GoodController1", GoodController1);

GoodController1.$inject = ["$scope", "$http", "$filter"];

function GoodController1($scope, $http, $filter){}
或者:
angular.module("myApp", [])
  .controller("GoodController1", 
              ["$scope", "$http", "$filter", function ($scope, $http, $filter){
     //...
}]);
为了回答你的问题,使用它不会有显著的性能提升。只是为了让你的代码更容易进行压缩并保证没有错误。这是因为压缩会更改变量名,在没有明确注释的情况下使用$scope会破坏你的代码。

8
你可以这样添加strict-di:

你也可以像这样添加strict-di:

 angular.bootstrap(document, ['app'], {
        strictDi: true
    });

使用Angular Meteor ES6类型应用程序时。

6

Angular的严格DI执行代码可压缩性。

当你的代码被压缩时,参数的名称会被缩短,这会破坏Angular的依赖注入(DI)。为了解决这个问题,Angular添加了两种(也许现在更多)替代方法来添加依赖关系。

可能最常见的方式,也是ng-annotate使用的方式,是将数组放置在作为第二个参数的函数中。依赖项是数组中倒数第二个元素之前的字符串,字符串是依赖项的名称。

controller.$inject(['$scope']);

angular.module('app', ['dependency']).controller('myCtrl', ['myFirstDep',
function(willBeInjectedHere){}])

你的ng-annotate可能没有在angular进行检查之前运行。确保你不要与annotate一起运行uglify,而是在annotate之前显式地执行。如果你的代码出现错误,则很可能有某个地方没有进行注释。


1
只是为了明确,ng-annotate 是一个构建工具,它将获取您的隐式依赖注入并添加内联数组注释。因此,您可以编写 angular.module('myApp', []).controller('myCtrl', function($q) { ... });,在 ng-annotate 运行后,它将变成:angular.module('myApp', []).controller('myCtrl', ['$q', function($q) {}]); - Tommy

4

良好的实践是使用 strict-di。当调用未使用显式函数注释的函数时,应用程序必须无法运行。这意味着使用的方法必须声明。使用 ng-strict-di 将确保应用程序符合依赖注入指南,并在不符合时无法运行。

您可以通过使用 ng-strict-di 来实现:

<html ng-app="myApp" ng-strict-di>

请查看开发者指南:https://docs.angularjs.org/guide/di


1
是的,但为什么?仅仅说指南这样规定并不能作为解释。其他人已经解释过了,因为缩小会破坏变量名,导致依赖注入器无法识别它们,所以你需要显式注释字符串,因为它们不会被破坏。 - Sámal Rasmussen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接