使用$ scope。$ emit和$ scope。$ on

本文翻译自:Working with $scope.$emit and $scope.$on

How can I send my $scope object from one controller to another using .$emit and .$on methods? 如何使用.$emit.$on方法将$scope对象从一个控制器发送到另一个控制器?

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

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

It doesn't work the way I think it should. 它不像我认为的那样工作。 How do $emit and $on work? $emit$on work如何运作?


#1楼

参考:https://stackoom.com/question/yqdK/使用-scope-emit和-scope-on


#2楼

First of all, parent-child scope relation does matter. 首先,父子范围关系确实很重要。 You have two possibilities to emit some event: 你有两种可能发出一些事件:

  • $broadcast -- dispatches the event downwards to all child scopes, $broadcast - 将事件向下发送到所有子范围,
  • $emit -- dispatches the event upwards through the scope hierarchy. $emit - 通过范围层次结构向上调度事件。

I don't know anything about your controllers (scopes) relation, but there are several options: 我对控制器(范围)关系一无所知,但有几种选择:

  1. If scope of firstCtrl is parent of the secondCtrl scope, your code should work by replacing $emit by $broadcast in firstCtrl : 如果范围firstCtrl是母公司secondCtrl范围,你的代码应该通过更换工作$emit$broadcastfirstCtrl

     function firstCtrl($scope) { $scope.$broadcast('someEvent', [1,2,3]); } function secondCtrl($scope) { $scope.$on('someEvent', function(event, mass) { console.log(mass); }); } 
  2. 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 (ie also secondCtrl ). 如果您的范围之间没有父子关系,您可以将$rootScope注入控制器并将事件广播到所有子范围(即secondCtrl )。

     function firstCtrl($rootScope) { $rootScope.$broadcast('someEvent', [1,2,3]); } 
  3. Finally, when you need to dispatch the event from child controller to scopes upwards you can use $scope.$emit . 最后,当您需要将子控制器中的事件调度到范围向上时,您可以使用$scope.$emit If scope of firstCtrl is parent of the secondCtrl scope: 如果firstCtrl范围是firstCtrl范围的父secondCtrl

     function firstCtrl($scope) { $scope.$on('someEvent', function(event, data) { console.log(data); }); } function secondCtrl($scope) { $scope.$emit('someEvent', [1,2,3]); } 

#3楼

You can call a service from your controller that returns a promise and then use it in your controller. 您可以从控制器调用返回承诺的服务,然后在控制器中使用它。 And further use $emit or $broadcast to inform other controllers about it. 并进一步使用$emit$broadcast来通知其他控制器。 In my case, I had to make http calls through my service, so I did something like this : 在我的情况下,我不得不通过我的服务进行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
        })
    }

and my service looks like this 我的服务看起来像这样

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

        }

    }])

#4楼

I would additionally suggest a 4th option as a better alternative to the proposed options by @zbynour. 我还建议第四个选项作为@zbynour提议选项的更好替代方案。

Use $rootScope.$emit rather than $rootScope.$broadcast regardless of the relationship between trasmitting and receiving controller. 无论传输和接收控制器之间的关系如何,都使用$rootScope.$emit而不是$rootScope.$broadcast That way, the event remains within the set of $rootScope.$$listeners whereas with $rootScope.$broadcast the event propagates to all children scopes, most of which will probably not be listeners of that event anyway. 这样,事件保持在$rootScope.$$listeners的集合中,而使用$rootScope.$broadcast ,事件传播到所有子范围,其中大多数可能不是该事件的监听器。 And of course in the receiving controller's end you just use $rootScope.$on . 当然,在接收控制器的最后,你只需使用$rootScope.$on

For this option you must remember to destroy the controller's rootScope listeners: 对于此选项,您必须记住销毁控制器的rootScope侦听器:

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

#5楼

This is my function: 这是我的功能:

$rootScope.$emit('setTitle', newVal.full_name);

$rootScope.$on('setTitle', function(event, title) {
    if (scope.item) 
        scope.item.name = title;
    else 
        scope.item = {name: title};
});

#6楼

<!DOCTYPE html>
<html>

<head>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script>
var app = angular.module('MyApp',[]);
app.controller('parentCtrl',function($scope){
  $scope.$on('MyEvent',function(event,data){    
    $scope.myData = data;
  });
 });

app.controller('childCtrl',function($scope){
  $scope.fireEvent = function(){ 
  $scope.$emit('MyEvent','Any Data');
  }  
 });
</script>
</head>
<body ng-app="MyApp">
<div ng-controller="parentCtrl" ng-model="myName">

{{myData}}

 <div ng-controller="childCtrl">
   <button ng-click="fireEvent()">Fire Event</button>
 </div>

</div>
</body>
</html>
发布了0 篇原创文章 · 获赞 73 · 访问量 55万+

猜你喜欢

转载自blog.csdn.net/w36680130/article/details/105357705