[Javascript] العمل مع نطاق $. $ emit و $ scope. $ on


Answers

وأود أن أقترح بالإضافة إلى ذلك خيار رابع كبديل أفضل للخيارات المقترحة بواسطةzbynour.

استخدم $rootScope.$emit بدلاً من $rootScope.$broadcast بغض النظر عن العلاقة بين trasitting وجهاز الاستقبال المتلقي. وبهذه الطريقة ، يظل الحدث ضمن مجموعة $rootScope.$$listeners بينما في $rootScope.$broadcast الحدث إلى جميع نطاقات الأطفال ، وربما لن يكون معظمهم مستمعين لهذا الحدث على أي حال. وبطبيعة الحال في نهاية وحدة تحكم المتلقي عليك فقط استخدام $rootScope.$on .

لهذا الخيار يجب أن تتذكر أن تدمر المستمعين rootScope وحدة التحكم:

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

كيف يمكنني إرسال كائن $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 و $on العمل؟




يعرض رمز أدناه اثنين من وحدات تحكم فرعية من حيث يتم إرسال الأحداث صعودا إلى وحدة تحكم الأصل (rootScope)

<body ng-app="App">

    <div ng-controller="parentCtrl">

        <p>City : {{city}} </p>
        <p> Address : {{address}} </p>

        <div ng-controller="subCtrlOne">
            <input type="text" ng-model="city" />
            <button ng-click="getCity(city)">City !!!</button>
        </div>

        <div ng-controller="subCtrlTwo">

            <input type="text" ng-model="address" />
            <button ng-click="getAddrress(address)">Address !!!</button>

        </div>

    </div>

</body>

var App = angular.module('App', []);

// parent controller
App.controller('parentCtrl', parentCtrl);

parentCtrl.$inject = ["$scope"];

function parentCtrl($scope) {

    $scope.$on('cityBoom', function(events, data) {
        $scope.city = data;
    });

    $scope.$on('addrBoom', function(events, data) {
        $scope.address = data;
    });
}

// sub controller one

App.controller('subCtrlOne', subCtrlOne);

subCtrlOne.$inject = ['$scope'];

function subCtrlOne($scope) {

    $scope.getCity = function(city) {

        $scope.$emit('cityBoom', city);    
    }
}

// sub controller two

App.controller('subCtrlTwo', subCtrlTwo);

subCtrlTwo.$inject = ["$scope"];

function subCtrlTwo($scope) {

    $scope.getAddrress = function(addr) {

        $scope.$emit('addrBoom', addr);   
    }
}

http://jsfiddle.net/shushanthp/zp6v0rut/




يمكنك استدعاء خدمة من وحدة التحكم الخاصة بك التي تعيد الوعد ثم استخدامها في وحدة التحكم الخاصة بك. وكذلك استخدام $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);
                });

        }

    }])



لإرسال $scope object من وحدة تحكم إلى أخرى ، سأناقش حول $rootScope.$broadcast و $rootScope.$emit هنا حيث يتم استخدامها أكثر من غيرها.

الحالة 1 :

$ $ rootScope البث: -

$rootScope.$broadcast('myEvent',$scope.data);//Here `myEvent` is event name

$rootScope.$on('myEvent', function(event, data) {} //listener on `myEvent` event

$rootScope لم يتم إتلاف المستمع تلقائيا. تحتاج إلى تدميرها باستخدام $destroy . من الأفضل استخدام $scope.$on يتم إتلاف $scope كمستمعين على $scope تلقائيًا ، أي بمجرد تدمير نطاق $.

$scope.$on('myEvent', function(event, data) {}

أو،

  var customeEventListener = $rootScope.$on('myEvent', function(event, data) {

  }
  $scope.$on('$destroy', function() {
        customeEventListener();
  });

الحالة 2:

. $ $ rootScope تنبعث منها:

   $rootScope.$emit('myEvent',$scope.data);

   $rootScope.$on('myEvent', function(event, data) {}//$scope.$on not works

الاختلاف الرئيسي في $ emit و $ broadcast هو أنه يجب أن يتم الإصغاء $ rootcope. $ emit event باستخدام $ rootScope. $ on ، لأن الحدث الذي تم إرساله لا ينزل من خلال شجرة النطاق. .
في هذه الحالة أيضا يجب عليك تدمير المستمع كما هو الحال في حالة البث $.

تصحيح:

أفضل عدم استخدام $rootScope.$broadcast + $scope.$on but use $rootScope.$emit+ $rootScope.$on . يمكن أن $rootScope.$broadcast + $scope.$on التحرير والسرد في حدوث مشكلات خطيرة في الأداء. هذا لأن الحدث سوف يتدفق من خلال جميع النطاقات.

تحرير 2 :

تم حل المشكلة التي تم تناولها في هذه الإجابة في الإصدار 1.2.7 من angular.js. يتجنب البث $ الآن حدوث فقاعات عبر نطاقات غير مسجلة ، ويتم تشغيله بالسرعة نفسها التي ينبعث منها الدولار.




<!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>



وفقاً لمستندات أحداث angularjs ، يجب أن يحتوي طرف المتلقي على وسائط ذات بنية مثل

params

- يكون حدث {الكائن} كائن الحدث الذي يحتوي على معلومات حول الحدث

- {object} args التي يتم تمريرها بواسطة المستدعي (لاحظ أن هذا يمكن أن يكون واحدًا أفضل لإرساله في كائن القاموس دائمًا)

$scope.$on('fooEvent', function (event, args) { console.log(args) }); من الكود الخاص بك

أيضا إذا كنت تحاول الحصول على جزء من المعلومات المشتركة المتاحة عبر وحدات تحكم مختلفة ، فهناك طريقة أخرى لتحقيق ذلك ، وهي خدمات زاوية.لأنه يمكن تخزين المعلومات الفردية وجمعها عبر أجهزة التحكم. وظائف الضبط في هذه الخدمة ، وفضح هذه الوظائف ، وجعل المتغيرات العالمية في الخدمة واستخدامها لتخزين المعلومات