474

コントローラー間で通信する正しい方法は何ですか?

私は現在、以下を含む恐ろしいファッジを使用していwindowます:

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);
    }
}
4

19 に答える 19

54

PubSub通信に$ rootScope 。$broadcastと$scope。$onを使用します。

また、この投稿を参照してください:AngularJS –コントローラー間の通信

于 2012-06-28T21:17:14.973 に答える
42

defineProperty はブラウザの互換性の問題があるので、サービスを利用することも考えられると思います。

angular.module('myservice', [], function($provide) {
    $provide.factory('msgBus', ['$rootScope', function($rootScope) {
        var msgBus = {};
        msgBus.emitMsg = function(msg) {
        $rootScope.$emit(msg);
        };
        msgBus.onMsg = function(msg, scope, func) {
            var unbind = $rootScope.$on(msg, func);
            scope.$on('$destroy', unbind);
        };
        return msgBus;
    }]);
});

次のようにコントローラーで使用します。

  • コントローラー1

    function($scope, msgBus) {
        $scope.sendmsg = function() {
            msgBus.emitMsg('somemsg')
        }
    }
    
  • コントローラー2

    function($scope, msgBus) {
        msgBus.onMsg('somemsg', $scope, function() {
            // your logic
        });
    }
    
于 2014-02-17T03:30:50.007 に答える
20

GridLinkedは、かなりうまく設計されていると思われるPubSubソリューションを投稿しました。このサービスは、ここで見つけることができます。

また、彼らのサービスの図:

メッセージング サービス

于 2012-07-10T20:47:26.397 に答える
15

イベントがスコープ階層を上下にバブルし、複雑なアプリケーションのパフォーマンスボトルに簡単に低下する可能性があるため、実際にエミットとブロードキャストを使用することは非効率的です。

サービスの利用をお勧めします。これが私のプロジェクトの1つであるhttps://gist.github.com/3384419に最近実装した方法です。

基本的な考え方-pubsub/eventバスをサービスとして登録します。次に、イベント/トピックをサブスクライブまたは公開する必要がある場所に、そのイベントバスを挿入します。

于 2012-08-18T04:30:08.183 に答える
14

サービス内で get メソッドと set メソッドを使用すると、コントローラー間でメッセージを簡単に渡すことができます。

var myApp = angular.module("myApp",[]);

myApp.factory('myFactoryService',function(){


    var data="";

    return{
        setData:function(str){
            data = str;
        },

        getData:function(){
            return data;
        }
    }


})


myApp.controller('FirstController',function($scope,myFactoryService){
    myFactoryService.setData("Im am set in first controller");
});



myApp.controller('SecondController',function($scope,myFactoryService){
    $scope.rslt = myFactoryService.getData();
});

HTML HTMLでは、このように確認できます

<div ng-controller='FirstController'>  
</div>

<div ng-controller='SecondController'>
    {{rslt}}
</div>
于 2014-10-14T15:10:40.583 に答える
8

元のコードについて - スコープ間でデータを共有したいようです。$scope 間で Data または State を共有するには、ドキュメントでサービスの使用が提案されています。

  • コントローラー間で共有されるステートレスまたはステートフル コードを実行するには — 代わりに angular サービスを使用します。
  • 他のコンポーネントのライフサイクルをインスタンス化または管理するため (たとえば、サービス インスタンスを作成するため)。

参照: Angular ドキュメントのリンクはこちら

于 2013-05-11T07:08:08.030 に答える
5

私は実際に Postal.js をコントローラー間のメッセージ バスとして使い始めました。

AMQP スタイルのバインディング、郵便が iFrame や Web ソケットと統合できる方法など、メッセージ バスとして多くの利点があります。

Postal を設定するためにデコレータを使用しました$scope.$bus...

angular.module('MyApp')  
.config(function ($provide) {
    $provide.decorator('$rootScope', ['$delegate', function ($delegate) {
        Object.defineProperty($delegate.constructor.prototype, '$bus', {
            get: function() {
                var self = this;

                return {
                    subscribe: function() {
                        var sub = postal.subscribe.apply(postal, arguments);

                        self.$on('$destroy',
                        function() {
                            sub.unsubscribe();
                        });
                    },
                    channel: postal.channel,
                    publish: postal.publish
                };
            },
            enumerable: false
        });

        return $delegate;
    }]);
});

このトピックに関するブログ投稿へのリンクは次のとおりです...
http://jonathancreamer.com/an-angular-event-bus-with-postal-js/

于 2014-05-07T22:55:31.157 に答える
3

$rootscope.emit相互コミュニケーションを実現するために使用される方法が気に入りました。グローバル空間を汚染することなく、クリーンでパフォーマンスに効果的なソリューションを提案します。

module.factory("eventBus",function (){
    var obj = {};
    obj.handlers = {};
    obj.registerEvent = function (eventName,handler){
        if(typeof this.handlers[eventName] == 'undefined'){
        this.handlers[eventName] = [];  
    }       
    this.handlers[eventName].push(handler);
    }
    obj.fireEvent = function (eventName,objData){
       if(this.handlers[eventName]){
           for(var i=0;i<this.handlers[eventName].length;i++){
                this.handlers[eventName][i](objData);
           }

       }
    }
    return obj;
})

//Usage:

//In controller 1 write:
eventBus.registerEvent('fakeEvent',handler)
function handler(data){
      alert(data);
}

//In controller 2 write:
eventBus.fireEvent('fakeEvent','fakeData');
于 2015-10-04T08:59:19.083 に答える
2

これが手っ取り早い方法です。

// Add $injector as a parameter for your controller

function myAngularController($scope,$injector){

    $scope.sendorders = function(){

       // now you can use $injector to get the 
       // handle of $rootScope and broadcast to all

       $injector.get('$rootScope').$broadcast('sinkallships');

    };

}

兄弟コントローラーのいずれかに追加する関数の例を次に示します。

$scope.$on('sinkallships', function() {

    alert('Sink that ship!');                       

});

もちろん、ここにあなたのHTMLがあります:

<button ngclick="sendorders()">Sink Enemy Ships</button>
于 2013-07-30T19:51:35.570 に答える
0
function mySrvc() {
  var callback = function() {

  }
  return {
    onSaveClick: function(fn) {
      callback = fn;
    },
    fireSaveClick: function(data) {
      callback(data);
    }
  }
}

function controllerA($scope, mySrvc) {
  mySrvc.onSaveClick(function(data) {
    console.log(data)
  })
}

function controllerB($scope, mySrvc) {
  mySrvc.fireSaveClick(data);
}
于 2015-03-12T07:23:35.630 に答える
0

AngularJS 組み込みサービスを使用$rootScopeして、このサービスを両方のコントローラーに挿入できます。その後、$rootScope オブジェクトで発生するイベントをリッスンできます。

$rootScope は$emit and $broadcast、イベント (カスタム イベントの場合もある) のディスパッチを担当し、$rootScope.$on関数を使用してイベント リスナーを追加する、呼び出される 2 つのイベント ディスパッチャを提供します。

于 2014-12-30T09:19:28.863 に答える
0

この hello 関数には、モジュール内のどこからでもアクセスできます

コントローラー1

 $scope.save = function() {
    $scope.hello();
  }

2 番目のコントローラー

  $rootScope.hello = function() {
    console.log('hello');
  }

詳細はこちら

于 2014-03-18T09:56:54.803 に答える