【问题标题】:Listen for multiple events on a $scope监听 $scope 上的多个事件
【发布时间】:2015-06-08 03:51:46
【问题描述】:

我有一个指令,它使用$scope.$on 将一些函数绑定到本地范围。

是否可以一次调用将同一个函数绑定到多个事件?

理想情况下,我可以这样做:

app.directive('multipleSadness', function() {
    return {
        restrict: 'C',
        link: function(scope, elem, attrs) {
            scope.$on('event:auth-loginRequired event:auth-loginSuccessful', function() {
                console.log('The Ferrari is to a Mini what AngularJS is to ... other JavaScript frameworks');
            });
        }
    };
});

但这不起作用。将逗号分隔的事件名称字符串替换为 ['event:auth-loginRequired', 'event:auth-loginConfirmed'] 的相同示例也不起作用。

这是什么工作:

app.directive('multipleSadness', function() {
    return {
        restrict: 'C',
        link: function(scope, elem, attrs) {

            scope.$on('event:auth-loginRequired', function() {
                console.log('The Ferrari is to a Mini what AngularJS is to ... other JavaScript frameworks');
            });
            scope.$on('event:auth-loginConfirmed', function() {
                console.log('The Ferrari is to a Mini what AngularJS is to ... other JavaScript frameworks');
            });
        }
    };
});

但这并不理想。

是否可以一次性将多个事件绑定到同一个函数?

【问题讨论】:

    标签: angularjs angularjs-directive


    【解决方案1】:

    其他答案 (Anders Ekdahl) 100% 正确...选择其中一个...但是...

    除此之外,你总是可以自己动手:

    // a hack to extend the $rootScope 
    app.run(function($rootScope) {
       $rootScope.$onMany = function(events, fn) {
          for(var i = 0; i < events.length; i++) {
             this.$on(events[i], fn);
          }
       }
    });
    
    app.directive('multipleSadness', function() {
        return {
            restrict: 'C',
            link: function(scope, elem, attrs) {
                scope.$onMany(['event:auth-loginRequired', 'event:auth-loginSuccessful'], function() {
                    console.log('The Ferrari is to a Mini what AngularJS is to ... other JavaScript frameworks');
                });
            }
        };
    });
    

    我想如果你真的想做.split(',') 你可以,但这是一个实现细节。

    【讨论】:

    • 你应该提交这个作为 PR 我可以使用这个。也许我会相信你的功劳。
    • 在每次迭代中检查长度是非常昂贵的;最好将长度分配给变量
    • @VerdiErelErgün“非常昂贵”?您每毫秒要计算多少次才能被击中?这是设置一些绑定的一次性调用。微优化并不是这里真正的重点......但是,如果他们真的愿意,可以for(var i = 0, len = events.length; i &lt; len; i++) { ... } ......甚至var i = events.length; while(i--) { ... }
    • @BenLesh 知道如何在隔离范围内进行这项工作吗?或者只是创建一个工厂方法并将范围传递给它?
    • 我是即时写的...但是您也需要能够结束侦听器... app.run(function($rootScope) { $rootScope.$onMany = function(events, fn) { var listeners = {} for(var i = 0; i
    【解决方案2】:

    AngularJS 不支持多事件绑定,但你可以这样做:

    var handler = function () { ... }
    angular.forEach("event:auth-loginRequired event:auth-loginConfirmed".split(" "), function (event) {
        scope.$on(event, handler);
    });
    

    【讨论】:

    • 您是否有理由使用 "event:auth-loginRequired event:auth-loginConfirmed".split(" ") 而不仅仅是 ['event:auth-loginRequired', 'event:auth -loginConfirmed']?
    • @RyanO'Neill 没有特殊原因 =) 使用单个字符串似乎比使用 ['','','',...] 更简洁。 OP 的示例也是用逗号分隔的单个字符串。
    • 谢谢。 JavaScript 就是这样,只是想确保我没有错过我应该知道的 Wat 时刻。
    【解决方案3】:

    是的。像这样:

    app.directive('multipleSadness', function() {
        return {
            restrict: 'C',
            link: function(scope, elem, attrs) {
    
                function sameFunction(eventId) {
                    console.log('Event: ' + eventId + '. The Ferrari is to a Mini what AngularJS is to ... other JavaScript frameworks.');
                }
    
                scope.$on('event:auth-loginRequired', function() {sameFunction('auth-loginRequired');});
                scope.$on('event:auth-loginConfirmed', function () {sameFunction('auth-loginConfirmed');});
            }
        };
    });
    

    但仅仅因为你可以,并不意味着你应该:)。如果事件继续传播到另一个侦听器并且在那里以不同的方式处理它们,那么也许有这样做的理由。如果这将是唯一的侦听器,那么您应该只发出(或广播)相同的事件。

    【讨论】:

    • 感谢您提供有关事件传播和事件 ID 的额外信息,知道了这一点,我明白为什么我所问的问题在本机上是不可能的。这些事件确实有不同的侦听器,但是这个侦听器需要对多个事件执行相同的操作。
    • 经过考虑,我已将代码重构为更 Angular。仍然有两个事件,但由于它们表示不同的事物(在重构中),因此没有理由将它们都绑定到同一个函数。谢谢指点。
    • 完全没问题。很高兴我能帮上忙。
    【解决方案4】:

    我不认为这是可能的,因为事件可能会向回调发送数据,如果您监听多个事件,您将不知道哪些数据来自哪个事件。

    我会做这样的事情:

    function listener() {
        console.log('event fired');
    }
    scope.$on('event:auth-loginRequired', listener);
    scope.$on('event:auth-loginConfirmed', listener);
    

    【讨论】:

      【解决方案5】:

      与 $rootScope.$onMany (来自@ben-lesh 的解决方案)一样,可以扩展 $on 方法:

      var $onOrigin = $rootScope.$on;
      
      $rootScope.$on = function(names, listener) {
        var self = this;
      
        if (!angular.isArray(names)) {
          names = [names];
        }
      
        names.forEach(function(name) {
          $onOrigin.call(self, name, listener);
        });
      
      };
      

      取自here

      【讨论】:

      • 如果您希望子作用域也继承修改后的功能,您应该修改$rootScope.__proto__.$on(或$rootScope.constructor.prototype.$on)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-19
      相关资源
      最近更新 更多