How to communicate correctly between angularJS controllers

A controller in AngularJS is a function that adds extra functionality to the view's scope ($scope), we use it to set the initial state of the scoped object and add custom behavior.

When we create a new controller, angularJS will help us generate and pass a new $scope object to the controller. In any part of the angularJS application, there is a parent scope, and the top level is ng- The level where the app is located, its parent scope is $rootScope.

The $root of each $scope points to the $rootScope, and $cope.$parent points to the parent scope.

The communication between cotrollers is essentially how the $scope where the current controller is located communicates with the $scope on other controllers.

There are usually 3 solutions:

Using the principle of scope inheritance, the child controller accesses the content in the parent controller.
Use events in angularJS, that is, use $on, $emit, $broadcast for message passing
Use services in angularJS The
first way

is the scope nested scope, which has certain usage restrictions, and the scope needs to be nested. In actual development, there are relatively few such scenarios, but it is not impossible. This method is simpler and more direct.

By default in angularJS, when a property cannot be found in the current scope, it will be searched in the parent scope, if not found until $rootScope is found. If it cannot be found in $rootScope, the program still runs, but the view is not updated.

Example

JavaScript

//Javascript

    app.controller('ParentController', function($scope) {

        $scope.person = {greeted: false};

    });

    app.controller('ChildController', function($scope) {

        $scope.sayHello = function() {

             $scope.person.name = 'Ari Lerner';

        };

    });

    //HTML

     <div ng-controller="ParentController">

       <div ng-controller="ChildController">

         <a ng-click="sayHello()">Say hello</a>

       </div>

       {{ person }}

     </div>

    //result

    {"greeted":true, "name": "Ari Lerner"}
The second way

Because the

There are 2 ways to deliver events: * $broadcast: To notify the entire event system (allowing any scope to handle this event), the triggered event must propagate down. * $emit: If you want to alert a global module, you need to pass the event up when you need to notify a higher level scope (such as $rootscope).

Use $on on the scope for event listening.

Example

JavaScript

app.controller('ParentController', function($scope) {
        $scope.$on('$fromSubControllerClick', function(e,data){
            console.log(data); // hello
        });
    });

    app.controller('ChildController', function($scope) {
        $scope.sayHello = function() {
            $scope.$emit('$fromSubControllerClick','hello');
        };
    });

    //HTML
     <div ng -controller="ParentController">
       <div ng-controller="
         <a ng-click="sayHello()">Say hello</a>
       </div>
     </div>
Another problem I want to talk about here is the performance problem of event propagation. The way of $broadcast+$on returns the notification For all sub-scopes, there will be performance problems here, so it is recommended to use the $emit+$on method. In order to further improve performance, the defined event handlers should be released together when the scope is destroyed.

Using $emit+$on requires us to bind event listeners to $rootScope, for example:

JavaScript

angular
    .module('MyApp')
    .controller('MyController', ['$scope', '$rootScope', function MyController ($scope, $rootScope) {
            var unbind = $rootScope.$on('someComponent.someCrazyEvent', function(){
                console.log('foo');
            });
            $scope.$on('$destroy', unbind);
        }
    ]);


Use the decorator to define a new event binding function:

JavaScript

angular
    .module('MyApp')
    .config(['$provide', function($provide){
        $provide.decorator('$rootScope', ['$ delegate', function($delegate){
            Object.defineProperty($delegate.constructor.prototype, '$onRootScope', {
                value: function(name, listener){
                    var unsubscribe = $delegate.$on(name, listener);
                    this .$on('$destroy', unsubscribe);
                    return unsubscribe;
                },
                enumerable: false
            });
            return $delegate;
        }]);
    }]);
Then when we define the event handler in the controller:

JavaScript

angular
    .module('MyApp')
    .controller('MyController', ['$scope', function MyController($scope) {
            $scope.$onRootScope('someComponent. someCrazyEvent', function(){
                console.log('foo');
            });
        }
    ]);
Personally strongly recommend this approach The

third way

Using the features of the service singleton pattern in angularJS, the service provides a A way to maintain data throughout the life cycle of the application, to communicate between controllers, and to ensure data consistency.

Generally, we will encapsulate the server to provide the application with an interface to access data, or to interact with remote data.

Example

JavaScript

var myApp = angular.module("myApp", []);
myApp.factory('Data', function() {
  return {
    name: "Ting"

});

myApp.controller('FirstCtrl', function($scope, Data) {
  $scope.data = Data;
  $scope.setName = function() {
    Data.name = "Jack";
  }
});

myApp.controller('SecondCtrl', function($scope, Data) {
  $scope.data = Data;
  $scope.setName = function() {
    Data.name = "Moby";
  }
});

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326607322&siteId=291194637