3

<main>私は、の間に親子のコントローラー関係を持ってい<div>ます<my-directive>

<main ng-controller="MainController">

    <nav>
        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
        </ul>
    </nav>

    <div ng-controller="AboutController">

    </div>

    <my-directive></my-directive>

</main>

MainController 内で、次のものを使用して $broadcast を実行します。

$scope.$broadcast('shoppingCartReady', msg);

AboutController 内で、次の方法でこの $broadcast を正常に受信できます。

angular.module('aboutModule', [])
    .controller('AboutController', require('./about/aboutController'));

var AboutController = function ($scope, $rootScope) {

    $scope.$on('shoppingCartReady', function(event, msg){
        console.log(msg);
    });

};

module.exports = [ '$scope', '$rootScope', AboutController];

ただし、リンク関数内で $broadcast を受信しようとすると、受信さ<my-directive>れないようです。

angular.module('shopModule', [])
    .directive('shopModuleDirective', require('./shopModuleDirective'))
    .directive('myDirective', require('./myDirective'));

var myDirective = function ($rootScope) {

    function link($scope, element, attrs, baseCtrl) {

        $scope.$on('shoppingCartReady', function (event, msg) {
            console.log(msg);
        });
    }

    return {
        restrict: 'E',
        require: '^shopModuleDirective',
        link: link
    };
};

return ['$rootScope', myDirective];

アップデート


ディレクティブ内にコントローラーを作成しました。

angular.module('shopModule', [])
    .directive('shopModuleDirective', require('./shopModuleDirective'))
    .directive('myDirective', require('./myDirective'));

var myDirective = function ($rootScope) {

    var controller = ["$scope", "$element", function ($scope, element) {
        console.log('waiting for .on....');
        $scope.$on('shoppingCartReady', function (event, cache) {
             console.log('shoppingCartReady .on rcvd!');
        });
    }]

    function link($scope, element, attrs, baseCtrl) {

        $scope.$on('shoppingCartReady', function (event, msg) {
            console.log(msg);
        });
    }

    return {
        restrict: 'E',
        require: '^shopModuleDirective',
        link: link
    };
};

return ['$rootScope', myDirective];

のログを見ることができます

console.log('waiting for .on....');

しかし、.on は受信されません。

アップデート:


考えられる原因は、スコープが「準備ができていない」ためだと思います。

broadcastMainController からのオリジナルの中で、setTimeアウトの後に別のものを実行すると、すべて.onが受信されます。

メインコントローラー:

$scope.$broadcast('shoppingCartReady', msg);

setTimeout(function(){
    $scope.$broadcast('shoppingCartReady', msg);
}, 8000);
4

2 に答える 2

4

ドキュメントから:

$broadcast(名前、引数);

登録された $rootScope.Scope リスナーに通知するイベント名をすべての子スコープ (およびその子スコープ) に下向きにディスパッチします。

あなたのディレクティブのように、新しいスコープを作成していないので、あなたはあなたと同じスコープレベルにいると思いますMainController. この場合、あなたは childScope にいないMainControllerので、そこでイベントをトリガーすることはできません。次のいずれかを試します。

  1. 常に を介してイベントをブロードキャストします$rootScope.$broadcast。他のすべてのスコープは の子$rootScopeであるため、 でイベントに登録すると$scope.$on、それを受け取ります。AngularJS で $rootScope.$broadcast を使用する理由にも興味があるかもしれません。

  2. ディレクティブに孤立した$scope. それは childScope として機能し、同様に機能するMainControllerはずです。ディレクティブの $scope の分離

  3. オプションの他、 との併用1.も可能です。詳細については、$rootScope.$broadcast と $scope.$emit を参照してください。$rootScope.$emit$rootScope.$on

1.ディレクティブに孤立したスコープを持たせたくない場合があるため、私は常にオプションを選択しました。

于 2016-04-27T07:38:15.080 に答える
3

競合状態があります。

myDirectiveコントローラーとポストリンク関数は の後に実行され、リスナーはイベントがトリガーMainControllerされた後に設定されます。shoppingCartReady

優れたテスト可能なディレクティブ設計の経験則は、すべてのスコープ関連のロジックをコントローラーに保持することです。リンク関数と$onInitフックは、コンパイルされた DOM コンテンツの操作など、他の場所ではなく、そこで発生する必要があるものに正確に使用されます。

あまり明白ではありませんが、特徴的な使用例linkは、実行の望ましい順序です (リンク後の関数は、子から親へと逆の順序で実行されます)。MainControllerディレクティブになり、コントローラーではなく関数scope.$broadcast('shoppingCartReady', msg)で実行される場合link、これにより適切な実行順序が保証されます。

コントローラーコードをゼロ$timeoutにラップすると、コードも延期されます

$timeout(function(){
    $scope.$broadcast('shoppingCartReady', msg);
});

children ディレクティブで関数をリンクした後に実行されますが、コードの臭いも示されます。これは、スコープ イベントがディレクティブ コミュニケーションのあまり望ましくない方法であり、アンチパターンになりやすい理由の 1 つです。

これを処理する代替方法は、shoppingCartReadyイベントの内容によって異なりますが、現在のケースでは冗長です。子コントローラーが実行された時点で既に発生しているため、「ショッピングカートの準備ができている」と安全に想定できます。

このトピックの推奨読書: AngularJS のディレクティブ コントローラーとリンク タイミング

于 2016-04-27T14:13:30.373 に答える