it-swarm.asia

العمل باستخدام نطاق $. $ emit و $ scope

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

866
Paul Kononenko

بادئ ذي بدء ، علاقة نطاق الوالدين والطفل لا يهم. لديك احتمالان لإصدار بعض الأحداث:

  • $broadcast - يرسل الحدث لأسفل إلى جميع النطاقات الفرعية ،
  • $emit - يرسل الحدث للأعلى من خلال التسلسل الهرمي للنطاق.

لا أعرف أي شيء عن علاقة وحدات التحكم (النطاقات) ، ولكن هناك عدة خيارات:

  1. إذا كان نطاق firstCtrl هو الأصل لنطاق secondCtrl ، فيجب أن يعمل الرمز الخاص بك عن طريق استبدال $emit بـ $broadcast في firstCtrl:

    function firstCtrl($scope)
    {
        $scope.$broadcast('someEvent', [1,2,3]);
    }
    
    function secondCtrl($scope)
    {
        $scope.$on('someEvent', function(event, mass) { console.log(mass); });
    }
    
  2. في حالة عدم وجود علاقة بين الوالدين والطفل بين النطاقات الخاصة بك ، يمكنك حقن $rootScope في وحدة التحكم وبث الحدث لجميع النطاقات الفرعية (أي أيضًا secondCtrl).

    function firstCtrl($rootScope)
    {
        $rootScope.$broadcast('someEvent', [1,2,3]);
    }
    
  3. أخيرًا ، عندما تحتاج إلى إرسال الحدث من وحدة تحكم تابعة إلى النطاقات لأعلى ، يمكنك استخدام $scope.$emit. إذا كان نطاق firstCtrl هو أصل نطاق secondCtrl:

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

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

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

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

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

كيف يمكنني إرسال كائن نطاق $ الخاص بي من وحدة تحكم إلى أخرى باستخدام. $ emit و. $ على الأساليب؟

يمكنك إرسال أي كائن تريده داخل التسلسل الهرمي لتطبيقك ، بما في ذلك نطاق $ .

إليك فكرة سريعة حول كيفية البث و البث العمل.

لاحظ العقد أدناه ؛ جميع المتداخلة داخل العقدة 3. يمكنك استخدام البث و تنبعث منها عندما يكون لديك هذا السيناريو.

ملاحظة: عدد كل عقدة في هذا المثال تعسفي ؛ يمكن أن يكون بسهولة رقم واحد. الرقم اثنين. أو حتى الرقم 1،348. كل رقم هو مجرد معرف لهذا المثال. الهدف من هذا المثال هو إظهار تداخل Angular التحكم/التوجيهات.

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

تحقق من هذه الشجرة. كيف تجيب على الأسئلة التالية؟

ملاحظة: هناك طرق أخرى للإجابة على هذه الأسئلة ، ولكن هنا سنناقش البث و تنبعث منها . أيضًا ، عند قراءة النص أدناه ، افترض أن لكل رقم ملفه الخاص (التوجيه ، جهاز التحكم) ، على سبيل المثال. one.js ، two.js ، three.js.

كيف العقدة 1 التحدث إلى العقدة 3 ؟

في الملف one.js

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

في الملف three.js - العقدة العليا لجميع العقد الفرعية اللازمة للتواصل.

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

كيف تتحدث العقدة 2 مع العقدة 3؟

في الملف two.js

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

في الملف three.js - العقدة العليا لجميع العقد الفرعية اللازمة للتواصل.

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

كيف تتحدث العقدة 3 مع العقدة 1 و/أو العقدة 2؟

في الملف three.js - العقدة العليا لجميع العقد الفرعية اللازمة للتواصل.

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

في الملف one.js && two.js أيهما الملف الذي تريد التقاط الرسالة أو كليهما.

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

كيف تتحدث العقدة 2 مع العقدة 1؟

في الملف two.js

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

في الملف three.js - العقدة العليا لجميع العقد الفرعية اللازمة للتواصل.

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

في الملف one.js

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

لكن

عندما يكون لديك كل هذه العقد الفرعية المتداخلة تحاول الاتصال بهذه الطريقة ، فسترى بسرعة العديد من $ on's ، $ broadcast - ، و $ emit's .

هنا هو ما أحب القيام به.

في عقدة الوالدين العلوية ( 3 في هذه الحالة ...) ، والتي قد تكون وحدة التحكم الرئيسية الخاصة بك ...

لذلك ، في الملف three.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] };
}

في الملف three.js - العقدة العليا لجميع العقد الفرعية اللازمة للتواصل.

تعاملنا بالفعل هذا واحد تذكر؟

في الملف one.js

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

ستظل بحاجة إلى استخدام $ on مع كل قيمة محددة تريد التقاطها ، ولكن الآن يمكنك إنشاء ما تريد في أي من العقد دون الحاجة إلى القلق بشأن كيفية توصيل الرسالة عبر العقدة الأصل الفجوة ونحن اللحاق والبث عام pushChangesToAllNodes .

أتمنى أن يساعدك هذا...

109
SoEzPz

لإرسال $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.$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 والبث $ في أن $ rootScope. يجب أن يتم الاستماع إلى حدث emit $ باستخدام $ rootScope. $ on ، لأن الحدث المنبعث لا يأتي أبداً عبر شجرة النطاق. .
في هذه الحالة أيضًا ، يجب عليك إتلاف المستمع كما في حالة البث $.

تصحيح:

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

تحرير 2 :

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

38
Ved

يجب عليك استخدام $ rootScope لإرسال الأحداث والتقاطها بين وحدات التحكم في نفس التطبيق. حقن التبعية $ 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); });
        }
}

الأحداث المرتبطة بالكائن نطاق دولار تعمل فقط في وحدة تحكم المالك. يتم الاتصال بين وحدات التحكم عن طريق $ rootScope أو الخدمات.

10
kyasar

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

        }

    }])
6
ribhu
<!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>
4
Prashant_M

هذه هي وظيفتي:

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

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

انتهى بي الأمر بإضافة مكتبة EventEmitter خارجية للمشروع كخدمة وحقنها في أي مكان أحتاج إليه. لذلك يمكنني أن "تنبعث منها" و "على" أي شيء في أي مكان دون الاهتمام بالميراث النطاق. إنها مشكلة أقل بهذه الطريقة وبالتأكيد أداء أفضل. أيضا أكثر قابلية للقراءة بالنسبة لي.

دعم أحرف البدل: EventEmitter2

أداء جيد: eventemitter3

بديل آخر: بالتنقيط

3
Mustafa Dokumacı

يمكن استخدام النطاق (النطاقات) لنشر الحدث وإرساله إلى نطاق الأطفال أو أحد الوالدين.

$ emit - ينشر الحدث إلى أصل. $ البث - نشر الحدث للأطفال. $ on - طريقة الاستماع إلى الأحداث ، التي نشرها $ emit والبث $.

مثال (index.html:

<div ng-app="appExample" ng-controller="EventCtrl">
      Root(Parent) scope count: {{count}}
  <div>
      <button ng-click="$emit('MyEvent')">$emit('MyEvent')</button>
      <button ng-click="$broadcast('MyEvent')">$broadcast('MyEvent')</button><br>

      Childrent scope count: {{count}} 
  </div>
</div>

مثال app.js:

angular.module('appExample', [])
.controller('EventCtrl', ['$scope', function($scope) {
  $scope.count = 0;
  $scope.$on('MyEvent', function() {
    $scope.count++;
  });
}]);

هنا يمكنك اختبار الرمز: http://jsfiddle.net/zp6v0rut/41/

2
Vasyl Gutnyk

يظهر أدناه رمز اثنين من وحدات التحكم الفرعية من حيث يتم إرسال الأحداث صعودا إلى وحدة تحكم الأصل (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/

2
Shushanth Pallegar

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

params

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

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

$scope.$on('fooEvent', function (event, args) { console.log(args) }); من التعليمات البرمجية الخاصة بك

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

0
Wajih Siddiqui

أسهل طريقة :

HTML

  <div ng-app="myApp" ng-controller="myCtrl"> 

        <button ng-click="sendData();"> Send Data </button>

    </div>

جافا سكريبت

    <script>
        var app = angular.module('myApp', []);
        app.controller('myCtrl', function($scope, $rootScope) {
            function sendData($scope) {
                var arrayData = ['sam','rumona','cubby'];
                $rootScope.$emit('someEvent', arrayData);
            }

        });
        app.controller('yourCtrl', function($scope, $rootScope) {
            $rootScope.$on('someEvent', function(event, data) {
                console.log(data); 
            }); 
        });
    </script>
0
Sangwin Gawande