javascript 在不注入 $rootScope 的情况下对指令中的角度事件做出反应

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19623412/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 16:13:24  来源:igfitidea点击:

Reacting on angular events in a directive without injecting $rootScope

javascriptangularjsangularjs-directiveangularjs-scope

提问by Adam Boczek

I wonder if you have an example of a directive code that reacts on angular events like $routeChangeErrorwithout injecting $rootScopein to it (to use $onin link function). It breaks in my opinion MV* pattern and "produces" smell-code (gives the possibility to manipulate root scope in a directive). Thanks in advance.

我想知道你是否有一个指令代码的例子,它对角度事件做出反应,比如$routeChangeError没有注入$rootScope它($on在链接函数中使用)。在我看来,它打破了 MV* 模式并“产生”了气味代码(提供了在指令中操纵根范围的可能性)。提前致谢。

采纳答案by Nikos Paraskevopoulos

If you are only listening for events, you don't have to use the $rootScope; do e.g. $scope.$on("$routeChangeError")on the scope of the directive, from either controller or link function.

如果您只监听事件,则不必使用$rootScope; 例如$scope.$on("$routeChangeError")在指令的范围内,从控制器或链接功能。

You see the "$routeChangeError"is broadcasted from the $rootScope, so all children receive it.

你看到"$routeChangeError"是从 广播的$rootScope,所以所有的孩子都会收到它。

回答by tennisgent

No. There isn't any way to listen to Angular events without having some sort of access to $scope. That is one of the main reasons they have the $rootScopeservice, so that you can gain access to $scopewhile in a service or some other module.

不。没有任何方法可以在没有某种访问权限的情况下收听 Angular 事件$scope。这是他们拥有该$rootScope服务的主要原因之一,因此您可以$scope在服务或其他模块中访问。

However, in a directive, you don't need to inject $rootScopebecause you already have an isolate scope in the directive in the linking function.

但是,在指令中,您不需要注入,$rootScope因为您已经在链接函数的指令中具有隔离范围。

For example:

例如:

.directive('myDirective', function(){
    return {
        restrict: 'A',
        link: function(scope, elem, attrs){
            scope.$on('some-event', function(e){
                // respond to event here
            });
        }
    };
});

Your scopevariable is an "isolate" scope so it cannot affect its parent scope in any way. This does however have some strange side effects if you're trying to emit an event out to some sister-level module, because Angular events only $emitupwards or $broadcastdownwards through the scope hierarchy. If you are not, then the above example should work perfectly. If you are, then the following example is one way to do it:

您的scope变量是一个“隔离”范围,因此它不能以任何方式影响其父范围。但是,如果您尝试将事件发送到某个姊妹级模块,这确实会产生一些奇怪的副作用,因为 Angular 事件只能$emit向上或$broadcast向下通过作用域层次结构。如果你不是,那么上面的例子应该可以完美地工作。如果您是,那么以下示例是一种方法:

.directive('myDirective', function($rootScope){
    var isolateScope = $rootScope.new();  // creates a new isolate copy of $rootScope
    return {
        restrict: 'A',
        link: function(scope, elem, attrs){
            isolateScope.$on('some-event', function(e){
                // respond to event here
            });
        }
    };
});

This will create a similar isolate copy of $rootScopeso that any changes you make to it will not affect other modules or services. This will prevent any issues with "smell-code"as you called it.

这将创建一个类似的隔离副本,$rootScope以便您对其所做的任何更改都不会影响其他模块或服务。这将防止"smell-code"您调用它的任何问题。

回答by Stewie

$onmethod is defined on internal Scope.prototype, and since each scope in Angular is created from Scopeconstructor this means each scope has a $onmethod available on itself. There's no need to inject $rootScope, just call the $onmethod on directive linking function's scope directly:

$on方法是在 internal 上定义的Scope.prototype,并且由于 Angular 中的每个作用域都是从Scope构造函数创建的,这意味着每个作用域都有一个$on自身可用的方法。不需要注入$rootScope,只需直接调用$on指令链接函数作用域上的方法:

app.directive('myDirective', function(){
  return function(scope, element, attrs){
    scope.$on('$routeChangeError', function(){
      // ...
    });
  }
});