scope - AngularJS में नियंत्रकों के बीच संवाद करने का सही तरीका क्या है?




(13)

असल में उत्सर्जन और प्रसारण का उपयोग अक्षम है क्योंकि घटना स्कोप पदानुक्रम को ऊपर और नीचे बुलबुला करती है जो जटिल अनुप्रयोग के लिए प्रदर्शन बोतल में आसानी से गिरावट कर सकती है।

मैं एक सेवा का उपयोग करने का सुझाव दूंगा। यहां बताया गया है कि मैंने हाल ही में अपनी परियोजनाओं में से एक में इसे कैसे कार्यान्वित किया - https://gist.github.com/3384419

मूल विचार - एक सेवा के रूप में एक पबब / घटना बस पंजीकृत करें। फिर उस ईवेंटबस को इंजेक्ट करें जहां आपको कभी भी सब्सक्राइब करने या ईवेंट / विषयों को प्रकाशित करने की आवश्यकता होती है।

नियंत्रकों के बीच संवाद करने का सही तरीका क्या है?

मैं वर्तमान में window जुड़े एक भयानक झुकाव का उपयोग कर रहा हूँ:

function StockSubgroupCtrl($scope, $http) {
    $scope.subgroups = [];
    $scope.handleSubgroupsLoaded = function(data, status) {
        $scope.subgroups = data;
    }
    $scope.fetch = function(prod_grp) {
        $http.get('/api/stock/groups/' + prod_grp + '/subgroups/').success($scope.handleSubgroupsLoaded);
    }
    window.fetchStockSubgroups = $scope.fetch;
}

function StockGroupCtrl($scope, $http) {
    ...
    $scope.select = function(prod_grp) {
        $scope.selectedGroup = prod_grp;
        window.fetchStockSubgroups(prod_grp);
    }
}

आप AngularJS बिल्ड-इन सेवा $rootScope का उपयोग कर सकते हैं और अपने दोनों नियंत्रकों में इस सेवा को इंजेक्ट कर सकते हैं। फिर आप रूट्सकोप ऑब्जेक्ट पर निकाल दिए गए ईवेंट के लिए सुन सकते हैं।

$ rootScope दो इवेंट डिस्पैचर प्रदान करता है जिसे $emit and $broadcast कहा जाता है जो घटनाओं को प्रेषित करने के लिए ज़िम्मेदार होते हैं (कस्टम ईवेंट हो सकते हैं) और ईवेंट श्रोता जोड़ने के लिए $rootScope.$on उपयोग करें।


आप मॉड्यूल में कहीं भी इस हैलो फ़ंक्शन तक पहुंच सकते हैं

नियंत्रक एक

 $scope.save = function() {
    $scope.hello();
  }

दूसरा नियंत्रक

  $rootScope.hello = function() {
    console.log('hello');
  }

यहां अधिक जानकारी


आपको सेवा का उपयोग करना चाहिए, क्योंकि $rootscope पूरे एप्लिकेशन से एक्सेस है, और यह लोड बढ़ाता है, या यदि आपका डेटा अधिक नहीं है तो आप रूटपरैम का उपयोग करते हैं।


किसी सेवा के भीतर विधियों को प्राप्त करने और सेट करने का उपयोग करके आप नियंत्रकों के बीच संदेशों को बहुत आसानी से पारित कर सकते हैं।

var myApp = angular.module("myApp",[]);

myApp.factory('myFactoryService',function(){


    var data="";

    return{
        setData:function(str){
            data = str;
        },

        getData:function(){
            return data;
        }
    }


})


myApp.controller('FirstController',function($scope,myFactoryService){
    myFactoryService.setData("Im am set in first controller");
});



myApp.controller('SecondController',function($scope,myFactoryService){
    $scope.rslt = myFactoryService.getData();
});

एचटीएमएल एचटीएमएल में आप इस तरह की जांच कर सकते हैं

<div ng-controller='FirstController'>  
</div>

<div ng-controller='SecondController'>
    {{rslt}}
</div>

कोणीय 1.5 शुरू करना और यह घटक आधारित विकास फोकस है। घटकों के लिए बातचीत करने के लिए अनुशंसित तरीका 'आवश्यकता' संपत्ति के उपयोग और संपत्ति बाइंडिंग (इनपुट / आउटपुट) के माध्यम से होता है।

एक घटक के लिए एक और घटक की आवश्यकता होगी (उदाहरण के लिए रूट घटक) और इसके नियंत्रक का संदर्भ प्राप्त करें:

angular.module('app').component('book', {
    bindings: {},
    require: {api: '^app'},
    template: 'Product page of the book: ES6 - The Essentials',
    controller: controller
});

फिर आप अपने बच्चे के घटक में रूट घटक के तरीकों का उपयोग कर सकते हैं:

$ctrl.api.addWatchedBook('ES6 - The Essentials');

यह मूल घटक नियंत्रक समारोह है:

function addWatchedBook(bookName){

  booksWatched.push(bookName);

}

यहां एक पूर्ण वास्तुशिल्प अवलोकन है: घटक संचार


मुझे इस तरह से पसंद आया कि $rootscope.emit प्राप्त करने के लिए $rootscope.emit का उपयोग कैसे किया गया था। मैं वैश्विक अंतरिक्ष प्रदूषित किए बिना स्वच्छ और प्रदर्शन प्रभावी समाधान का सुझाव देता हूं।

module.factory("eventBus",function (){
    var obj = {};
    obj.handlers = {};
    obj.registerEvent = function (eventName,handler){
        if(typeof this.handlers[eventName] == 'undefined'){
        this.handlers[eventName] = [];  
    }       
    this.handlers[eventName].push(handler);
    }
    obj.fireEvent = function (eventName,objData){
       if(this.handlers[eventName]){
           for(var i=0;i<this.handlers[eventName].length;i++){
                this.handlers[eventName][i](objData);
           }

       }
    }
    return obj;
})

//Usage:

//In controller 1 write:
eventBus.registerEvent('fakeEvent',handler)
function handler(data){
      alert(data);
}

//In controller 2 write:
eventBus.fireEvent('fakeEvent','fakeData');

मूल कोड के बारे में - ऐसा प्रतीत होता है कि आप स्कॉप्स के बीच डेटा साझा करना चाहते हैं। डेटा या राज्य को $ स्कोप के बीच साझा करने के लिए दस्तावेज़ों का उपयोग एक सेवा का उपयोग करने का सुझाव देता है:

  • नियंत्रकों में साझा स्टेटलेस या स्टेटफुल कोड चलाने के लिए - इसके बजाय कोणीय सेवाओं का उपयोग करें।
  • अन्य घटकों के जीवन चक्र को तत्काल या प्रबंधित करने के लिए (उदाहरण के लिए, सेवा उदाहरण बनाने के लिए)।

रेफरी: कोणीय डॉक्स लिंक यहाँ


मैंने वास्तव में नियंत्रकों के बीच एक संदेश बस के रूप में Postal.js का उपयोग करना शुरू कर दिया है।

एएमक्यूपी स्टाइल बाइंडिंग जैसी संदेश बस के रूप में इसके बहुत सारे फायदे हैं, जिस तरह से डाक w / iFrames और वेब सॉकेट को एकीकृत कर सकता है, और कई और चीजें।

मैंने $scope.$bus पर डाक सेट अप करने के लिए एक सजावट का उपयोग किया $scope.$bus ...

angular.module('MyApp')  
.config(function ($provide) {
    $provide.decorator('$rootScope', ['$delegate', function ($delegate) {
        Object.defineProperty($delegate.constructor.prototype, '$bus', {
            get: function() {
                var self = this;

                return {
                    subscribe: function() {
                        var sub = postal.subscribe.apply(postal, arguments);

                        self.$on('$destroy',
                        function() {
                            sub.unsubscribe();
                        });
                    },
                    channel: postal.channel,
                    publish: postal.publish
                };
            },
            enumerable: false
        });

        return $delegate;
    }]);
});

यहां विषय पर एक ब्लॉग पोस्ट का एक लिंक है ...
http://jonathancreamer.com/an-angular-event-bus-with-postal-js/


यहां का शीर्ष उत्तर एक कोणीय समस्या से आसपास एक काम था जो अब मौजूद नहीं है (कम से कम संस्करणों> 1.2.16 और "शायद पहले") @zumalifeguard ने उल्लेख किया है। लेकिन मैं इन सभी उत्तरों को वास्तविक समाधान के बिना पढ़ रहा हूं।

ऐसा लगता है कि जवाब अब होना चाहिए

  • $rootScope से $broadcast उपयोग करें
  • स्थानीय $scope से $on का उपयोग करके सुनें जिसे घटना के बारे में जानने की आवश्यकता है

तो प्रकाशित करने के लिए

// EXAMPLE PUBLISHER
angular.module('test').controller('CtrlPublish', ['$rootScope', '$scope',
function ($rootScope, $scope) {

  $rootScope.$broadcast('topic', 'message');

}]);

और सदस्यता लें

// EXAMPLE SUBSCRIBER
angular.module('test').controller('ctrlSubscribe', ['$scope',
function ($scope) {

  $scope.$on('topic', function (event, arg) { 
    $scope.receiver = 'got your ' + arg;
  });

}]);

Plunkers

यदि आप श्रोता को स्थानीय $scope पर पंजीकृत करते हैं, तो संबंधित नियंत्रक को हटा दिए जाने पर इसे स्वचालित रूप से $destroy कर दिया जाएगा।



ग्रिडलिंक्ड ने एक पबसब समाधान पोस्ट किया जो कि बहुत अच्छी तरह से डिजाइन किया गया प्रतीत होता है। सेवा here मिल सकती here

उनकी सेवा का एक चित्र भी:


function mySrvc() {
  var callback = function() {

  }
  return {
    onSaveClick: function(fn) {
      callback = fn;
    },
    fireSaveClick: function(data) {
      callback(data);
    }
  }
}

function controllerA($scope, mySrvc) {
  mySrvc.onSaveClick(function(data) {
    console.log(data)
  })
}

function controllerB($scope, mySrvc) {
  mySrvc.fireSaveClick(data);
}