微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

scope – 在AngularJS中的控制器之间进行通信的正确方法是什么?

什么是控制器之间通信的正确方法

我目前使用一个可怕的软糖涉及窗口:

function StockSubgroupCtrl($scope,$http) {
    $scope.subgroups = [];
    $scope.handleSubgroupsLoaded = function(data,status) {
        $scope.subgroups = data;
    }
    $scope.fetch = function(prod_grp) {
        $http.get('/api/stock/groups/' + prod_grp + '/subgroups/').success($scope.handleSubgroupsLoaded);
    }
    window.fetchStockSubgroups = $scope.fetch;
}

function StockGroupCtrl($scope,$http) {
    ...
    $scope.select = function(prod_grp) {
        $scope.selectedGroup = prod_grp;
        window.fetchStockSubgroups(prod_grp);
    }
}
编辑:在这个答案解决的问题已经解决在angular.js version 1.2.7. $ broadcast现在避免冒泡在未注册的范围和运行就像$ emit一样快。

所以,现在你可以:

>使用$ broadcast从$ rootScope
> listen使用$ on从需要知道事件的本地$ scope

原始答案下面

我强烈建议不要使用$ rootScope。$ broadcast $ scope。$ on,而是$ rootScope。$ emit $ rootScope。$ on。前者可能导致严重的性能问题,由@numan提出。这是因为事件将向下滚动通过所有范围。

但是,后者(使用$ rootScope。$ emit $ rootScope。$ on)没有这种情况,因此可以用作快速通信通道!

从$ emit的angular文档:

dispatches an event name upwards through the scope hierarchy notifying the registered

因为没有范围超过$ rootScope,没有冒泡发生。使用$ rootScope。$ emit()/ $ rootScope。$ on()作为EventBus是完全安全的。

但是,在控制器中使用它时有一个困扰。如果你直接绑定到控制器中的$ rootScope。$ on(),你必须在你的局部$ scope被销毁时自己清除绑定。这是因为控制器(与服务相反)可以在应用程序的生命周期内被实例化多次,这将导致绑定总结,最终在整个地方创建内存泄漏:)

要取消注册,只需监听$ scope的$ destroy事件,然后调用$ rootScope。$ on返回的函数

angular
    .module('MyApp')
    .controller('MyController',['$scope','$rootScope',function MyController($scope,$rootScope) {

            var unbind = $rootScope.$on('someComponent.someCrazyEvent',function(){
                console.log('foo');
            });

            $scope.$on('$destroy',unbind);
        }
    ]);

我会说,这不是一个真正的角度具体的事情,因为它也适用于其他EventBus实现,以及,你必须清理资源。

但是,你可以让你的生活更轻松的情况下。例如,你可以猴子补丁$ rootScope并给它一个$ onRootScope订阅$ rootScope上发出的事件,但也直接清除处理程序时,局部$ scope被销毁。

最纯洁的方式猴子补丁$ rootScope提供这样的$ onRootScope方法将通过一个装饰器(一个运行块可能会做它只是罚款,但pssst,不告诉任何人)

为了确保$ onRootScope属性在枚举超过$ scope时不会出现意外,我们使用Object.defineproperty()并将enumerable设置为false。请记住,您可能需要一个ES5垫片。

angular
    .module('MyApp')
    .config(['$provide',function($provide){
        $provide.decorator('$rootScope',['$delegate',function($delegate){

            Object.defineProperty($delegate.constructor.prototype,'$onRootScope',{
                value: function(name,listener){
                    var unsubscribe = $delegate.$on(name,listener);
                    this.$on('$destroy',unsubscribe);

                    return unsubscribe;
                },enumerable: false
            });


            return $delegate;
        }]);
    }]);

使用这种方法,来自上面的控制器代码可以简化为:

angular
    .module('MyApp')
    .controller('MyController',function MyController($scope) {

            $scope.$onRootScope('someComponent.someCrazyEvent',function(){
                console.log('foo');
            });
        }
    ]);

所以作为所有这些的最终结果,我强烈建议您使用$ rootScope。$ emit $ scope。$ onRootScope。

Btw,我试图说服有角度的团队解决角核心内的问题。这里有一个讨论:https://github.com/angular/angular.js/issues/4574

这里是一个jsperf,显示多少影响$ broadcastbrings到表在一个体面的场景,只有100 $范围。

http://jsperf.com/rootscope-emit-vs-rootscope-broadcast

原文地址:https://www.jb51.cc/angularjs/147489.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐