如何将我的$scope对象从一个控制器发送到另一个使用。$emit和。$on方法?

function firstCtrl($scope) {
    $scope.$emit('someEvent', [1,2,3]);
}

function secondCtrl($scope) {
    $scope.$on('someEvent', function(mass) { console.log(mass); });
}

这不是我想的那样。$emit和$on如何工作?


当前回答

如何将我的$scope对象从一个控制器发送到另一个使用。$emit和。$on方法?

你可以在应用的层次结构中发送任何你想要的对象,包括$scope。

下面简要介绍一下广播和发射的工作原理。

注意下面的节点;都嵌套在节点3中。在这种情况下使用broadcast和emit。

注意:本例中每个节点的编号是任意的;它很容易成为第一;数字2;甚至是1348。对于这个例子,每个数字只是一个标识符。这个例子的重点是展示Angular控制器/指令的嵌套。

                 3
           ------------
           |          |
         -----     ------
         1   |     2    |
      ---   ---   ---  ---
      | |   | |   | |  | |

看看这棵树。你如何回答以下问题?

注意:还有其他方法来回答这些问题,但这里我们将讨论广播和发射。此外,当阅读下面的文本时,假设每个数字都有自己的文件(指令,控制器)例如one.js, two.js, three.js。

节点1如何与节点3通信?

在文件1。js中

scope.$emit('messageOne', someValue(s));

在文件3 .js中——所有需要通信的子节点的最上面的节点。

scope.$on('messageOne', someValue(s));

节点2如何与节点3通信?

在文件two.js中

scope.$emit('messageTwo', someValue(s));

在文件3 .js中——所有需要通信的子节点的最上面的节点。

scope.$on('messageTwo', someValue(s));

节点3如何与节点1和/或节点2通信?

在文件3 .js中——所有需要通信的子节点的最上面的节点。

scope.$broadcast('messageThree', someValue(s));

在文件one.js && two.js中,你想要捕获消息的文件或两者都有。

scope.$on('messageThree', someValue(s));

节点2如何与节点1通信?

在文件two.js中

scope.$emit('messageTwo', someValue(s));

在文件3 .js中——所有需要通信的子节点的最上面的节点。

scope.$on('messageTwo', function( event, data ){
  scope.$broadcast( 'messageTwo', data );
});

在文件1。js中

scope.$on('messageTwo', someValue(s));

然而

当所有这些嵌套的子节点试图像这样通信时,您将很快看到许多$on、$broadcast和$emit。

这是我喜欢做的事情。

在最上面的父节点中(在本例中是3…),这可能是你的父控制器…

在文件3。js中

scope.$on('pushChangesToAllNodes', function( event, message ){
  scope.$broadcast( message.name, message.data );
});

现在,在任何子节点中,您只需要$emit消息或使用$on捕获它。

注意:通常很容易在一个嵌套路径中进行交叉对话,而不需要使用$emit、$broadcast或$on,这意味着大多数用例都是用于试图让节点1与节点2通信,反之亦然。

节点2如何与节点1通信?

在文件two.js中

scope.$emit('pushChangesToAllNodes', sendNewChanges());

function sendNewChanges(){ // for some event.
  return { name: 'talkToOne', data: [1,2,3] };
}

在文件3 .js中——所有需要通信的子节点的最上面的节点。

我们已经处理过了,记得吗?

在文件1。js中

scope.$on('talkToOne', function( event, arrayOfNumbers ){
  arrayOfNumbers.forEach(function(number){
    console.log(number);
  });
});

您仍然需要对想要捕获的每个特定值使用$on,但是现在您可以在任何节点中创建您喜欢的任何值,而不必担心在捕获和广播通用的pushChangesToAllNodes时如何通过父节点间隙获取消息。

其他回答

首先,亲子范围关系确实很重要。你有两种可能触发事件:

$broadcast——向下分派事件到所有子作用域, $emit——通过作用域层次结构向上分派事件。

我对你的控制器(作用域)关系一无所知,但有几个选项:

If scope of firstCtrl is parent of the secondCtrl scope, your code should work by replacing $emit by $broadcast in firstCtrl: function firstCtrl($scope) { $scope.$broadcast('someEvent', [1,2,3]); } function secondCtrl($scope) { $scope.$on('someEvent', function(event, mass) { console.log(mass); }); } In case there is no parent-child relation between your scopes you can inject $rootScope into the controller and broadcast the event to all child scopes (i.e. also secondCtrl). function firstCtrl($rootScope) { $rootScope.$broadcast('someEvent', [1,2,3]); } Finally, when you need to dispatch the event from child controller to scopes upwards you can use $scope.$emit. If scope of firstCtrl is parent of the secondCtrl scope: function firstCtrl($scope) { $scope.$on('someEvent', function(event, data) { console.log(data); }); } function secondCtrl($scope) { $scope.$emit('someEvent', [1,2,3]); }

如何将我的$scope对象从一个控制器发送到另一个使用。$emit和。$on方法?

你可以在应用的层次结构中发送任何你想要的对象,包括$scope。

下面简要介绍一下广播和发射的工作原理。

注意下面的节点;都嵌套在节点3中。在这种情况下使用broadcast和emit。

注意:本例中每个节点的编号是任意的;它很容易成为第一;数字2;甚至是1348。对于这个例子,每个数字只是一个标识符。这个例子的重点是展示Angular控制器/指令的嵌套。

                 3
           ------------
           |          |
         -----     ------
         1   |     2    |
      ---   ---   ---  ---
      | |   | |   | |  | |

看看这棵树。你如何回答以下问题?

注意:还有其他方法来回答这些问题,但这里我们将讨论广播和发射。此外,当阅读下面的文本时,假设每个数字都有自己的文件(指令,控制器)例如one.js, two.js, three.js。

节点1如何与节点3通信?

在文件1。js中

scope.$emit('messageOne', someValue(s));

在文件3 .js中——所有需要通信的子节点的最上面的节点。

scope.$on('messageOne', someValue(s));

节点2如何与节点3通信?

在文件two.js中

scope.$emit('messageTwo', someValue(s));

在文件3 .js中——所有需要通信的子节点的最上面的节点。

scope.$on('messageTwo', someValue(s));

节点3如何与节点1和/或节点2通信?

在文件3 .js中——所有需要通信的子节点的最上面的节点。

scope.$broadcast('messageThree', someValue(s));

在文件one.js && two.js中,你想要捕获消息的文件或两者都有。

scope.$on('messageThree', someValue(s));

节点2如何与节点1通信?

在文件two.js中

scope.$emit('messageTwo', someValue(s));

在文件3 .js中——所有需要通信的子节点的最上面的节点。

scope.$on('messageTwo', function( event, data ){
  scope.$broadcast( 'messageTwo', data );
});

在文件1。js中

scope.$on('messageTwo', someValue(s));

然而

当所有这些嵌套的子节点试图像这样通信时,您将很快看到许多$on、$broadcast和$emit。

这是我喜欢做的事情。

在最上面的父节点中(在本例中是3…),这可能是你的父控制器…

在文件3。js中

scope.$on('pushChangesToAllNodes', function( event, message ){
  scope.$broadcast( message.name, message.data );
});

现在,在任何子节点中,您只需要$emit消息或使用$on捕获它。

注意:通常很容易在一个嵌套路径中进行交叉对话,而不需要使用$emit、$broadcast或$on,这意味着大多数用例都是用于试图让节点1与节点2通信,反之亦然。

节点2如何与节点1通信?

在文件two.js中

scope.$emit('pushChangesToAllNodes', sendNewChanges());

function sendNewChanges(){ // for some event.
  return { name: 'talkToOne', data: [1,2,3] };
}

在文件3 .js中——所有需要通信的子节点的最上面的节点。

我们已经处理过了,记得吗?

在文件1。js中

scope.$on('talkToOne', function( event, arrayOfNumbers ){
  arrayOfNumbers.forEach(function(number){
    console.log(number);
  });
});

您仍然需要对想要捕获的每个特定值使用$on,但是现在您可以在任何节点中创建您喜欢的任何值,而不必担心在捕获和广播通用的pushChangesToAllNodes时如何通过父节点间隙获取消息。

你可以从控制器调用一个返回承诺的服务,然后在控制器中使用它。并进一步使用$emit或$broadcast通知其他控制器。 在我的情况下,我必须通过我的服务进行http调用,所以我做了这样的事情:

function ParentController($scope, testService) {
    testService.getList()
        .then(function(data) {
            $scope.list = testService.list;
        })
        .finally(function() {
            $scope.$emit('listFetched');
        })


    function ChildController($scope, testService) {
        $scope.$on('listFetched', function(event, data) {
            // use the data accordingly
        })
    }

我的服务是这样的

    app.service('testService', ['$http', function($http) {

        this.list = [];

        this.getList = function() {
            return $http.get(someUrl)
                .then(function(response) {
                    if (typeof response.data === 'object') {
                        list = response.data.results;

                        return response.data;
                    } else {
                        // invalid response
                        return $q.reject(response.data);
                    }

                }, function(response) {
                    // something went wrong
                    return $q.reject(response.data);
                });

        }

    }])

你必须使用$rootScope在同一个应用程序的控制器之间发送和捕获事件。下面是一个工作示例。

app.controller('firstCtrl', function($scope, $rootScope) {        
        function firstCtrl($scope) {
        {
            $rootScope.$emit('someEvent', [1,2,3]);
        }
}

app.controller('secondCtrl', function($scope, $rootScope) {
        function secondCtrl($scope)
        {
            $rootScope.$on('someEvent', function(event, data) { console.log(data); });
        }
}

链接到$scope对象的事件只在所有者控制器中工作。控制器之间的通信是通过$rootScope或Services完成的。

我还会建议第四个选项,作为@zbynour提议的选项的更好替代方案。

使用rootScope美元。$emit而不是$rootScope。不管发送和接收控制器之间的关系。这样,事件就保留在$rootScope的集合中。$$监听器,而$rootScope。将事件传播到所有子作用域,其中大多数子作用域可能不是该事件的监听器。当然,在接收控制器端,你只需使用$rootScope。$on。

对于这个选项,你必须记得销毁控制器的rootScope监听器:

var unbindEventHandler = $rootScope.$on('myEvent', myHandler);
$scope.$on('$destroy', function () {
  unbindEventHandler();
});