javascript - شرح - العمل مع نطاق $. $ emit و $ scope. $ on




angularjs شرح (9)

كيف يمكنني إرسال كائن النطاق $ الخاص بي من جهاز تحكم إلى آخر باستخدام. $ emit و $.

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

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

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

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

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

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

ملاحظة: هناك طرق أخرى للإجابة على هذه الأسئلة ، ولكن هنا سنناقش البث والإرسال . أيضا ، عند قراءة النص أدناه ، افترض أن كل رقم يحتوي على ملف خاص به (توجيه ، وحدة تحكم) ex 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));

ومع ذلك

عندما يكون لديك كل هذه العقد التابعة المتداخلة تحاول التواصل مثل هذا ، سترى بسرعة العديد من $ ، و $ $ ، و $ sit .

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

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

لذلك ، في ملف three.js

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

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

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

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

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


أسهل طريقة :

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>

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

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

الأداء الجيد: eventemitter3

بديل آخر: Drip


لإرسال $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. يتجنب البث $ الآن حدوث فقاعات عبر نطاقات غير مسجلة ، ويتم تشغيله بالسرعة نفسها التي ينبعث منها الدولار.


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

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

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

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

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

params

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

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

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

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


يعرض رمز أدناه اثنين من وحدات تحكم فرعية من حيث يتم إرسال الأحداث صعودا إلى وحدة تحكم الأصل (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 - ينشر الحدث إلى أحد الوالدين. بث $ - ينشر الحدث للأطفال. $ on - method to listen the events، propagated by $ emit and $ broadcast.

مثال 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/


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